Atof() number of significant decimal digits returned.

Hello everyone !

I have this question about using atof() function.

Is there a way i can "adjust" it so that it returns only 1 significant decimal digit instead of the number it returns by default ?

Thank you so much !

You can print fewer significant digits, but you cannot control the number of significant digits in a floating point number. You just get a different number if you try.

For example, the number 0.1 cannot even be represented exactly using floating point notation.

Short answer is no. The float data type has a fixed number of significant digits. (Actually a fixed number of significant binary digits, which does not correspond to an exact number of decimal digits.)

You have two options.

1. Let the float continue with whatever value it has until the point where you need to print it. When you print it, using Serial.print(), by default it will have 2 decimal places. If you want some other precision, use dtostrf() to turn it into a string, then print the string.

2. Round or truncate the value held in the float to the precision you want. Do this if you need further calculations to reflect that the input value has already been rounded. But when you print the value, it will still show the full precision of a float, so see point 1 above.

jremington:
For example, the number 0.1 cannot even be represented exactly using floating point notation.

I think that 0.1 can be represented exactly by floating point notation and not 0.37 and the similar (for example).

``````void setup()
{
Serial.begin(9600);
float x = 0.37;
float y;

long m = *(long*)&x;
Serial.println(m, HEX);
//--------------------
long *ptry;
ptry = (long)&y;
*ptry = m;
Serial.println(y, 23);
}

void loop()
{

}
``````

GolamMostafa:
I think that 0.1 can be represented exactly by floating point notation and not 0.37 and the similar

Absolutely nonsense. In binary, the only numbers (less than 1) that can be exactly represented in a finite number of bits to the right of the binary point are the real numbers n / 2^k. For example, the decimal number 1/10 can’t be represented in a finite number of bits to the right of the binary point.

Likewise, in decimal, the only numbers (less than 1) that can be exactly represented in a finite number of digits to the right of the decimal point are the real numbers n / (2^j * 5^k). For example, the real number 1/3 can’t be exactly represented in a finite number of digits to the right of the decimal point.

EDIT:
It should go with out saying, but I’ll say it anyway. In the above, the values n, j, and k are integers >= 0. And, the resultant fractions are < 1.

My input is 0.1 (0.10000000000000000000000); after conversion and re-conversion, I have got 0.10000000000000000000000 back. So, the IEEE-754 (binary32) representation for 0.1 is exact.

My input is 0.37 (0.37000000000000000000000); after conversion and re-conversion, I have got 0.37000000476837158203125 back. So, the IEEE-754 (binary32) representation for 0.37 is not exact.

These are my understandings.

GolamMostafa:
These are my understandings.

You understanding is incorrect. That’s the effect of rounding during printing.

Here’s an exercise for you - Take out a pencil and paper and write down the exact representation of 1/10 in binary. I’ll get you started: 0.0001100110011…….
Now, please continue that until the answer is exactly 1/10. By that I don’t mean that you’ve run out of digits on your calculator, I mean EXACTLY.

If you finish that (which you never will), write down the EXACT decimal representation for 1/7. Again, I’ll get you started: 0.142857……

gfvalvo:
You understanding is incorrect. That’s the effect of rounding during printing.

Here’s an exercise for you - Take out a pencil and paper and write down the exact representation of 1/10 in binary. I’ll get you started: 0.0001100110011…….
Now, please continue that until the answer is exactly 1/10. By that I don’t mean that you’ve run out of digits on your calculator, I mean EXACTLY.

If you finish that (which you never will), write down the EXACT decimal representation for 1/7. Again, I’ll get you started: 0.142857……

0.1x2 = 0.2
0.2x2 = 0.4
0.4x2 = 0.8
0.8x2 = 1.6
0.6x2 = 1.2
0.2x2 = 0.4
0.4x2 = 0.8
0.8x2 = 1.6
0.6x2 = 1.2

The binary representation of 0.1 is: (0.000110011…)2
(0.000110011…)2
==> 0 + 0 + 0 + 1x2-4 + 1x2-5+0+0+1x2-8+1x2-9+…
==> 0 + 0 + 0 + 0.0625 + 0.03125 + 0 + 0 + 0.00390625 + 0.001953125 + …
==> 0.099609375…
==> (0.1) //rounding

So, the binary representation is not exact.

The IEEE-754 must be doing the same thing; hence, that representation for 0.1 is also not exact.

Thank you for giving time for my learning through the offering of a well designed exercise. (+).

That’s the effect of rounding during printing.

Cool!

Thank you all for taking time to answer me. I should have posted my code in the first place but i have them all at home and now i am away for a few days. I will try to explain dest way i can about what i want to do.

I have a gps receiver connected on a mega board. I receive the Nmea messages which are consisted of comma separated fields and store them in a char array. Then i use the strtok() function with comma as delimiter to locate the field of interest. The field contains a number like this for example (0.102) then i compare this number to an other number and based on which is smaller, i operate a relay.
So my real problem is that the number on the NMEA message slightly changes every second. Like this for example (0.102 , 0.103 , 0.101 etc) thus my relay opens and closes at high rate. Things in my code would be alot smootger if the number i am getting was not like this (0.101) but was like that(0.1)..
Maybe converting the 0.101 to 0.1 is a good option since when the characters are extracted from the char array then they are converted in float, so i do have a float variable i can manipulate. Though not sure how to...

Im stll open to suggestions

Thank you !

Typical XY-problem

Solution one, just crop the string to 0.1 before turning it into a float.

Or the better solution, use hysteresis

Im stll open to suggestions

Now that you have explained the REAL problem, post the code, using code tags.

There is no real problem, i dont have a "hidden agenda" or anything if that is what you are suspecting :).
Yes i wanted to know about atof() functionality ofcource in order to use it in many differet codes to get numbers and use them to calculate things but that is only normal isnt it? I know that some people ask for answers without providing information and expecting others to guess what the problem is. That is silly to say the least.
Ill post the code when i go to my computer and that will probably be the next few days. I have no intention to hide anything. Meanwhile i kindly ask for ideas if thats possible.

Also many big THANK you to all for answering the original question. Like i have mentioned in other topics it really is a big deal when someone passes his hardly earned knowledge to other people. I always have that in mind !

"X-Y" problems arise out of ignorance, not subterfuge, no-one is accusing you of anything underhand. Google "X-Y Problem".

As for suggestions, I made one in post #2...

Understood. No offence taken Ive actually never heard of this term. Will google it.

HellasT:

Actually, I just remembered there is a section about it at the bottom of the forum guide in the sticky post. It's such a common problem here...

I think that mycase is not really an X-Y problem because the original question in post 1 was aimed more to get to know the fuctionality of atof() function rather than solving the particular problrem in my code