float? Количество знаков целой и дробной частей XXXXXXX.xxxxxx

Ehehe
Offline
Зарегистрирован: 20.10.2020

Доброго времени суток!

При 

float J = 2451545 + 0.0009 + (27.560858/360) + 7598 = 2459143.0000000

но разделив на 10:

float J = (2451545 + 0.0009 + (27.560858/360) + 7598)/10 = получаю 245914.2968750

Как в первом случае получить адекватную мантиссу?

Юлианская дата - необходимо получить 2459142.968750

Спасибо!

P.S. Хотелось бы без компромиссов!

b707
Offline
Зарегистрирован: 26.05.2017

никак.

float с одинарной точностью не предназначен для точных вычислений, а double в ардуине нет. Во флоат в ардуино всего 6-7 значащих цифр. Это означает, что если у вас до запятой 6 цифр - то дробная часть не будет точной даже на уровне первого знака после запятой

Используйте целые числа. Особенно для дат...

Ehehe
Offline
Зарегистрирован: 20.10.2020
Но мне необходимо именно дробное...
2459142 - дни
.968750 - часы, минуты и секунды...
 
 
 
float shirota = 53.894835;                                            // широта Минск
float dolgota = 27.560858;                                            // долгота Минск
 
//radians(deg)  Перевод градусов в радианы
//degrees(rad)  Перевод радиан в градусы
 
 
void setup() {
  Serial.begin(9600);
 
}
 
void loop() {
 
  unsigned long JD = 2459143;                                                                         // Текущий юлианский день 2458850 2459141
  for (int i = 0; i < 7; i++ , JD++) {
    long julianOffset = 2451545;
    float JDN = (JD - julianOffset - 0.0009) - (dolgota / 360);                                           // Номер юлианского дня
    long n = round(JDN);
    float J = julianOffset + 0.0009 + (dolgota / 360) + n;                                                                    // средний солнечный полдень
    long m1 = round(357.5291 + 0.98560028 * (J - julianOffset)) % 360;                                                  // Солнечная средняя аномалия
    float m2 = (357.5291 + 0.98560028 * (J - julianOffset)) - round(357.5291 + 0.98560028 * (J - julianOffset));
    float M = m1 + m2;
    float C = (1.9148 * sin(radians(M))) + (0.02 * sin(2 * radians(M))) + (0.0003 * sin(3 * radians(M)));   // Уравнение центра
    long eclLonOfSun1 = round(M + C + 180 + 102.9372) % 360;                                               // Долгота эклиптики
    float eclLonOfSun2 = (M + C + 180 + 102.9372) - round(M + C + 180 + 102.9372);
    float eclLonOfSun = eclLonOfSun1 + eclLonOfSun2;
    float jTransit = J + (0.0053 * sin(radians(M))) - (0.0069 * sin(2 * radians(eclLonOfSun)));                    // Солнечный транзит
    float skloneniyeSun = asin(sin(radians(eclLonOfSun))) * sin(radians(23.45));                                 // Cклонение cолнца
 
    float hourCosNum = (sin(radians(-0.83)) - sin(radians(shirota)) * sin(skloneniyeSun));                // Часовой угол
    float hourDenom = (cos(radians(shirota)) * cos(skloneniyeSun));
    float hourAngle = acos(hourCosNum) / hourDenom;
 
    float finalJulianApproximation = (julianOffset + 0.0009 + ((degrees(hourAngle) + shirota) / 360) + n) / 100;       // Аппроксимации
    float jSet = finalJulianApproximation + (0.0053 * sin(radians(M))) - (0.0069 * sin(2 * radians(eclLonOfSun)));
  
 
    Serial.print(n);
    Serial.print('\t');
    Serial.print(J, 7);
    Serial.print('\t');
    Serial.print(M);
    Serial.print('\t');
    Serial.print(C, 8);
    Serial.print('\t');
    Serial.println(degrees(skloneniyeSun));
  }
  delay(5000000);
 
 
}
b707
Offline
Зарегистрирован: 26.05.2017

Ehehe пишет:

Но мне необходимо именно дробное...
2459142 - дни
.968750 - часы, минуты и секунды...

2.5 миллиона дней?

"да вы оптимист. батенька..." :))))

Я не знаю, зачем вам 2.5 миллиона дней, но для обычных дат все переводится в секунды и считается в целых числах

b707
Offline
Зарегистрирован: 26.05.2017

и еще раз повторю - вычислять сумму, где одно слагаемое очень большое, а второе очень маленькое, например :

2451545 + 0.0009

в виде флоат абсолютно бессмысленно. Можете сами убедится

 

Иногда улучшить точность можно, переписав правильно порядок операций

Например вот это

float J = 2451545 + 0.0009 + (27.560858/360) + 7598

надо делать вот так

float J =  (0.0009 + (27.560858/360))  + 7598 + 2451545

потери точности будут меньше

Ehehe
Offline
Зарегистрирован: 20.10.2020

b707 пишет:

Я не знаю, зачем вам 2.5 миллиона дней, но для обычных дат все переводится в секунды и считается в целых числах

Уравнение восхода солнца

2459142 - сегодняшний день по юлианскому календарю.

[/quote]

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Ehehe пишет:

b707 пишет:

Я не знаю, зачем вам 2.5 миллиона дней, но для обычных дат все переводится в секунды и считается в целых числах

Уравнение восхода солнца

2459142 - сегодняшний день по юлианскому календарю.

 

Ну так, как уже сказали, зачем вам float? Делайте в целых числах. Для данного случая unsigned long.

rkit
Offline
Зарегистрирован: 23.11.2016

Ehehe пишет:

float J = (2451545 + 0.0009 + (27.560858/360) + 7598)/10 = получаю 245914.2968750

Врешь. Число с такой точностью не поместится во float. Именно поэтому его нельзя использовать в данном случае.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Астротаймеры продаются за десятку у китайцев.
Прямо на дин рейку, в корпусе.
У меня в поселке таких уже лет пять 4 штуки стоят , свет включают.
https://mysku.ru/blog/aliexpress/31895.html

А формулы гляньте тут:
http://iopa4.narod.ru
Всё уже давно сделано, и даже на 8-ой меге

P.S.
Не помню название, но у Ардуины есть готовая библиотека
заката-восхода....

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ehehe пишет:

Но мне необходимо именно дробное...
Это высказывание внушает некоторые сомнения.
Но, если оно все-таки истинно, переходите на 32-разрядный контроллер, в котором есть нормальный double. Например, Arduino Due, ESP8266 или stm32.
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andriano пишет:
переходите на 32-разрядный контроллер, в котором есть нормальный double.
Не поможет. 

Переходить нужно на целые числа.

А вообще, для задачи восхода Солнца нужно просто выбросить весь колхоз вместе с формулами и пользоваться старой, доброй юниксовской time, благо, она есть.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вы лучше определитесь, что именно Вам нужно

Ehehe пишет:

именно дробное...

или время

Ehehe пишет:
восхода солнца

Если второе, так весь Ваш колхоз вместе с "дробными" нужно просто выбросить, ибо готовое решение уже есть в системных библиотеках. Если бы Вы потрудились поискать, прежде, чем постить, то нашли бы тему в которой есть просто готовый пример определения времени восхода для двух городов безо всяких флоатов.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ЕвгенийП пишет:

andriano пишет:
переходите на 32-разрядный контроллер, в котором есть нормальный double.
Не поможет. 

А, собственно, почему?

У double мантисса 48 разрядов - все больше, чем в long. Так что должно хватить (правильное округление - отдельный вопрос).

Любую техническую задачу можно решить разными способами. Если ТС умеет сделать через дробные числа и не умеет через целые - то почему нет?

rkit
Offline
Зарегистрирован: 23.11.2016

andriano пишет:

У double мантисса 48 разрядов - все больше, чем в long. Так что должно хватить (правильное округление - отдельный вопрос).

К разрядности контроллера это не имеет никакого значения. И не хватит.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

rkit пишет:

К разрядности контроллера это не имеет никакого значения.

Теоретически  - возможно.

Но на практике оказывается, что на 8-разрядном контроллере у double всего 32 разряда, тогда как на 32-разрядном - полноценные 64.

rkit
Offline
Зарегистрирован: 23.11.2016

Пожалуйста, не надо рассказывать про практику, когда твоя практика ограничена двумя контроллерами, да и там ты не разобрался как это всё работает.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

rkit пишет:

Пожалуйста, не надо рассказывать про практику, когда твоя практика ограничена двумя контроллерами, да и там ты не разобрался как это всё работает.

Практика - критерий истины.

И если контроллеры в моих проектах работают именно так, как я задумал, то, вероятно, все-таки разобрался.

rkit
Offline
Зарегистрирован: 23.11.2016

Или просто повезло.

В AVR нет float ну совсем. То, что ты делаешь, реализовано софтом, и точно так же может быть реализовано хоть с 32, хоть с 10, хоть со 156 бит. То же самое корректно для 32хбитных контроллеров без аппаратной поддержки float, коих великое множество.