2013-07-15 4 views
1

Я работаю на arduino с затмением. Я хочу преобразовать двойной массив char для хранения в EEPROM. Из другого вопроса я нашел ответ на эту проблему. Я изменил его, чтобы удовлетворить мои потребности. Но число, которое я возвращаю, не совсем то же самое.Напишите двойной EEPROM

Код:

#include "Arduino.h" 
#include "EEPROM.h" 

char finalArray[8]; 
double final; 
double d; 

int main(void) 
{ 
    init(); 
    setup(); 

    for (;;) 
     loop(); 

    return 0; 
} 


void setup() { 
    Serial.begin(115200); 
    d = 557.254; 
    char* byteArray = reinterpret_cast<char*>(&d); 

    for(int i=0;i<8;i++){ 
     EEPROM.write(i,byteArray[i]); 
    } 

    for(int i=0;i<8;i++){ 
      finalArray[i]=EEPROM.read(i); 
    } 

} 

void loop() { 

    final = *reinterpret_cast<double*>(finalArray); 
    double diff=d-final; 
    final+=diff; 
    Serial.println(d,9); 
    Serial.println(diff,9); 
    Serial.println(final,9); 

    delay(1000); 
} 

В терминале я получаю значение 958.25402 вместо 958.25400. И если я попрошу 9 десятичных цифр при печати, вместо 5, я получу номер 958.254028320. Какое решение?

Serial.print дают цифры:

557.254028320

0.000000000

557.254028320

Так что проблема при инициализации двойной д.

+0

Если вы вставляете 'printf (" d =% .17g. \ N ", d);' сразу после 'd = 958.254;', какой результат вы получаете? Если в цикле записи вы вставляете 'printf (« byteArray [% d] =% # x. \ N ", i, (unsigned char) byteArray [i]);', какой результат вы получаете? Если в считываемом цикле после каждого чтения вы вставляете 'printf (« finalArray [% d] =% # x. \ N ", i, (unsigned char) finalArray [i]);', какой результат вы получаете ? Это то же самое, что и исходные байты? –

+0

, когда меня интересует чтение, не печатая номер причины, которую я хочу использовать, для вычислений, поэтому в основном мне не нужно исправлять печать, но возвращаемое число. Я исправил код, и я дам вам результат, чтобы понять проблему. Проблема начинается с двойного d, который я даю. – kyrpav

ответ

4

Значение 958.2540283203125 результатов от преобразования 958.254 к float (в частности, к 32-битное значение двоичной плавающей точкой IEEE-754). Преобразование его в double (64-бит) должно производить 958.2540000000000190993887372314929962158203125.

Если код, как вы показали здесь, то ваш компилятор не поддерживает double правильно (стандарты C и C++ требует, чтобы десять цифр десятичной цифра может быть преобразована в double и обратно без изменения до десятичных цифр).

Для проверки работоспособности, вы должны распечатать dсразу после назначения. Вполне возможно, что в коде есть «забавный бизнес», который позже изменяет значение d. Если d = 958.254; приводит к значению d, являющемуся 958.2540283203125, то вам следует исследовать поддержку вашего компилятора для 64-битной с плавающей запятой. Если d - 958.2540000000000190993887372314929962158203125, а затем изменения, то вам следует изучить ошибку в вашей программе.

+0

Вы находитесь на правильном пути, AVR-GCC рассматривает удвоение как то же, что и float (32 бита). http://gcc.gnu.org/wiki/avr-gcc – user2461391

+0

@ user2461391: Спасибо. Это значит, что: Поскольку компилятор не поддерживает 'double' правильно, код не выполняет в соответствии с требованиями стандартов C и C++, и значение не может быть представлено более точно. OP нуждается в новом компиляторе или необходимо принять недостаток точности. –

+0

Скрытый в отсутствии поддержки для 8-байтового двойника - хороший совет. – jdr5ca

0

Вы пробовали с

d = 557.254000000d; 
+0

Ошибка: недопустимый суффикс «D» на плавающей константе.it не понимает его и дает синтаксическую ошибку. – kyrpav

Смежные вопросы