Double 64 bit conversion to 32 Float with precision losing
There is problem with Double 64 bit conversion to 32 Float with precision losing. Below two sketches,
Result on IND.I/O D21G board returns -0.00, on UNO board 123.00 (this is correct).
Any ideas ?
#include <UC1701.h>
#include <IEEE754tools.h>
static UC1701 lcd;
void setup() {
// put your setup code here, to run once:
lcd.begin();
}
void loop() {
// put your main code here, to run repeatedly:
byte tab[8];//decimal 123
tab[0] =B00000000;
tab[1] =B00000000;
tab[2] =B00000000;
tab[3] =B00000000;
tab[4] =B00000000;
tab[5] =B11000000;
tab[6] =B01011110;
tab[7] =B01000000;
float f = doublePacked2Float(tab);
lcd.setCursor(0,0);
lcd.print(f);
delay(1000);
//Result -0.00
}
#include <IEEE754tools.h>
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
byte tab[8];//decimal 123
tab[0] =B00000000;
tab[1] =B00000000;
tab[2] =B00000000;
tab[3] =B00000000;
tab[4] =B00000000;
tab[5] =B11000000;
tab[6] =B01011110;
tab[7] =B01000000;
float f = doublePacked2Float(tab);
Serial.println(f);
delay(1000);
//Result 123.00
}
/*------------------------------------------------------------*/
Next file :
Hi Janusz,
The D21G is 32-bit (4 bytes), and the 'double' data type is 8 bytes, so you can use this simple code based on 'union' to convert from bytes to double. You can cast the double into a float type, as in the last 2 lines, i assume that changes the precision of the number. Does that solve your issue?
SerialUSB.begin(9600);
while (!SerialUSB);
SerialUSB.println();
union double_8bytes {
double d;
byte b[8];
};
double_8bytes our_number;
our_number.b[0] = B00000000;
our_number.b[1] = B00000000;
our_number.b[2] = B00000000;
our_number.b[3] = B00000000;
our_number.b[4] = B00000000;
our_number.b[5] = B11000000;
our_number.b[6] = B01011110;
our_number.b[7] = B01000000;
SerialUSB.println(our_number.d);
float our_float = our_number.d;
SerialUSB.println(our_float);
Hi, Tom yes you have right. It's working fine. Thank you very much!
Hi Tom,
your code will work only with numbers with out fraction, try below 123.456. I receive 8 bytes (Modbus register 4x16bit unsigned int)
I need code which will transfer Doble 64bit to Float 32bit as it should do IEEE754tools library.On UNO boards it works fine and on DG21G it returns 0.00 or -0.00.
SerialUSB.begin(9600);
while (!SerialUSB);
SerialUSB.println();
union double_8bytes {
double d;
byte b[8];
};
double_8bytes our_number;
our_number.b[0] = B01110111;
our_number.b[1] = B10111110;
our_number.b[2] = B10011111;
our_number.b[3] = B00011010;
our_number.b[4] = B00101111;
our_number.b[5] = B11011101;
our_number.b[6] = B01011110;
our_number.b[7] = B01000000;
//Decimal: 123.456
SerialUSB.println(our_number.d);
float our_float = our_number.d;
SerialUSB.println(our_float);
------------------------------------------------------------------------------------------------------------------------------------
SECOND EXAMPLE:
this is code which is tested on UNO and Industrino D21G board with results:
//Industrino D21G output :
40 5E DD 2F 1A 9F BE 77 --> -3.482
123.456 --> 20 76 E9 79 E0 0 0 0 --> 0.000
//Uno board output ( change SerialUSB to Serial in code):
40 5E DD 2F 1A 9F BE 77 --> 123.456
123.456 --> 40 5E DD 2F 37 88 3D FE --> 123.456
Why the same code returns different results on UNO and D21G ?
#include <IEEE754tools.h>
void setup() {
// put your setup code here, to run once:
SerialUSB.begin(9600);
while(!SerialUSB){}
byte tab[8];
//FLOAT: 123.456
//HEX: 40 5E DD 2F 1A 9F BE 77
/* tab[0] =B01110111;
tab[1] =B10111110;
tab[2] =B10011111;
tab[3] =B00011010;
tab[4] =B00101111;
tab[5] =B11011101;
tab[6] =B01011110;
tab[7] =B01000000;*/
tab[0] =0x77;
tab[1] =0xBE;
tab[2] =0x9F;
tab[3] =0x1A;
tab[4] =0x2F;
tab[5] =0xDD;
tab[6] =0x5E;
tab[7] =0x40;
for (int j=7; j>=0; j--){
SerialUSB.print(tab[j],HEX);
SerialUSB.print(' ');
}
SerialUSB.print("--> ");
SerialUSB.print(doublePacked2Float(tab),3);
SerialUSB.println();
byte fab[8];
SerialUSB.print("123.456 --> ");
float2DoublePacked(123.456, fab);
for (int i=7; i>=0; i--){
SerialUSB.print(fab[i],HEX);
SerialUSB.print(' ');
}
SerialUSB.print(" --> ");
SerialUSB.print(doublePacked2Float(fab),3);
SerialUSB.println();
SerialUSB.println();
delay(5000);
}
void loop() {
// put your main code here, to run repeatedly:
}
Your answer
Please try to give a substantial answer. If you wanted to comment on the question or answer, just use the commenting tool. Please remember that you can always revise your answers - no need to answer the same question twice. Also, please don't forget to vote - it really helps to select the best questions and answers!
Keep Informed
About This Forum
This community is for professionals and enthusiasts of our products and services.
Read GuidelinesQuestion tools
Stats
Asked: 10/10/17, 12:53 PM |
Seen: 3055 times |
Last updated: 10/12/17, 7:20 AM |
Hi Janusz, I have tried your example, and it get a decimal number 123.456 so the code seems to work, can you test it too? If you use the below code, you can see the difference in precision between float and double. 123.4560000000 vs 123.4560012817 SerialUSB.begin(9600); while (!SerialUSB); SerialUSB.println(); union double_8bytes { double d; byte b[8]; }; double_8bytes our_number; our_number.b[0] = B01110111; our_number.b[1] = B10111110; our_number.b[2] = B10011111; our_number.b[3] = B00011010; our_number.b[4] = B00101111; our_number.b[5] = B11011101; our_number.b[6] = B01011110; our_number.b[7] = B01000000; SerialUSB.println(our_number.d,10); float our_float = our_number.d; SerialUSB.println(our_float,10);