Float to int conversion issue

Hi,

In my code below, I'm trying to save some radio station frequencies to EEPROM and read it back to an array. Issue I'm facing is the first station number is always returning as 8119 where as it I'm expecting 8120 and the rest of the station returns perfectly correct.
May I know what I'm doing wrong here.

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  while (!Serial) {
  }

  float x = 0.00;
  int eeAddress = 0;

  //Put some random numbers to eeprom
  EEPROM.put(eeAddress, 81.2);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 83.0);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 85.2);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 90.1);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 92.6);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 93.0);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 93.5);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 94.4);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 100.5);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 101.8);
  eeAddress += sizeof(float); 
  EEPROM.put(eeAddress, 106.6);

  float stations[20];

  //Read back those saved to an array
  for (int a=0; a <= 10; a++){
    stations[a] = EEPROM.get(eeAddress, x);
    eeAddress += sizeof(float); 
  }

  //Print the array values to terminal
  for (int a=0; a < 20; a++){
    Serial.print(stations[a]);
    Serial.print("\t");
    Serial.println(int(stations[a] * 100));
  }
}

void loop() {
  /* Empty loop */
}

image

Don't save them as floats, save them as scaled ints

1 Like

"81.2" is one of many, many examples of a number that cannot be exactly represented by a float. This calculator will show you why.

Store the integer 812 instead, and divide the integer by 10.0 if you need a float value.

1 Like

@dinesha77
You might argue that when 85.20x100 comes as 8520, then 81.20x100 should aslo come as 8120.

You get 8119 instead of 8120 due to loss of "information"/accuracy during inter-conversions of data from one form to another, which you can see from the following brief discussion. Thats why as @jremington has said that all float numbers cannot be represented exactly.

1. When you declare float x = 81.2;, then this 32-bit number : 0x42A26666 is stored into memory locations. The number is created based on the following template (Fig-1) called IEEE-754 standard.

IEEE754Float
Figure-1:

2. Now, you multiply 81.2 by 100 and you get 8120.00 from which you want to isolate the integer part (8120); but, it comes as 8119.

3. You can feel from Fig-1 that the process of isolating the integer part involves inter-conversions of data during which the accuracy is lost. So, follow the suggestions of @TheMemberFormerlyKnownAsAWOL and @jremington to store your numbers as integers if you desire to see no change in them.

1 Like

You can recover by rounding when you convert to integer:
Serial.println(int(stations[a] * 100 + 0.5));

@johnwasser Yes! Your trick is providing what the @dinesha77 has wanted (Fig-1); but, it is at the cost of hiding the inherent feature of the floating point representation.

smdxx
Figure-1:

That's what Serial.print() does. It rounded "81.199..." to "81.20" for display.

1 Like