View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
PIC24EP divide by 10 causes rouding error [SOLVED] |
Posted: Mon Dec 04, 2017 9:07 am |
|
|
Device: PIC24EP512GP806
Compiler: 5.026
Without going into details... I have an 8-bit value in an EEPROM and I receive data from a UART. The values received are numbers from 0-180 which in reality are 0 to 18.0 in 0.1 increments.
The value in the EEPROM also represents a number from 0 to 18.0 in 0.1 increments but given that floats cannot be written in an EEPROM, it is simply multiplied by 10 then written.
Then the received values get compared with that of the EEPROM's as x10 integers so if the MCU gets 171 and the EEPROM value is 168, then really, I know that I'm comparing 17.1 to 16.8 but the comparison is done at the raw integer level therefore 171 compared to 168. The whole point here is that the received value is checked to see if it's smaller or greater than that of the EEPROM's.
This is all fine at the MCU level because both values are integers and easy to compare.
Where I have a problem is that the values need to get presented to a user on a display as floating points like 17.1 or 6.4 or 12.3. In order to achieve this, I simply divide both values by 10 and present them using fprintf <%2.1f>.
Here are quick tests I made with the results of the /10 operation:
61 / 10 = 6.0 <-- problem
62 / 10 = 6.2
63 / 10 = 6.2 <-- problem
64 / 10 = 6.4
103 / 10 = 10.3
105 / 10 = 10.5
129 / 10 = 12.8 <-- problem
At first, I thought that only uneven numbers caused the issue. Then I thought it was uneven numbers below 10 but now I see that there's no pattern - it's just something with the calculation.
Any suggestion?
In the background it's not an issue and all works fine, it's only with the presentation to the user that it is causing a calculation error.
Thanks,
Ben
Last edited by benoitstjean on Tue Dec 05, 2017 9:28 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19511
|
|
Posted: Mon Dec 04, 2017 9:15 am |
|
|
You don't have to convert to float.
The problem with converting to float is that it inherently has values it cannot encode exactly. When you trim these, you get the rounding errors. There are numbers that float cannot accurately code.
Use %w.
Just print your integer with %4.1w |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Dec 04, 2017 10:06 am |
|
|
Ha! Works!
So, using %w, does it increase the processing time by a lot versus using a simple %f ?
Ben |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19511
|
|
Posted: Mon Dec 04, 2017 11:29 am |
|
|
No, hugely less.....
It works only with integers. No floats involved. It prints an integer (or a long integer using LW), as an integer, but with a decimal point added. Designed for people using integers to represent fixed point numbers (as you are).
Since all the divisions are integer, probably about 50* faster than using %f. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Dec 04, 2017 1:35 pm |
|
|
Ok, thank you so much for your time and input. As always, greatly appreciated.
Ben |
|
|
|