Page 1 of 1
Truncated floating point numbers
Posted: Wed Jul 18, 2012 12:54 pm
by Mantas
Hello support,
Why flowcode ARM v5 is truncating floating point values when compiling to C (and then I suppose to hex and so on...)
For example value that I need to use of constant PI = 3.1415926535897932384626433832795028841971
Is truncated in C code to value of "volatile MX_FLOAT FCV_PI = (3.141593);" which is unacceptable
I suppose the other bigger values of other floating points is also truncated to (0.000000), and this produces unacceptable errors in my calculations.
I have a hunch that it is also truncating big numbers stored in const double LUT[x][y][z]; in the supplementary code and this is the reason why I am getting totally unexpected final results.
So how can I fix this, or is this something that you can fix?
Best regards,
Mantas
Re: Truncated floating point numbers
Posted: Wed Jul 18, 2012 3:58 pm
by JonnyW
Hello.
There is a fix for PI. Flowcode will truncate all floats at this point to a 6-digit precision. I have added a fix for the next release that ups this to 15 digits, but I think this is the most that can be offered.
In the meantime a fix for PI assuming this is a constant (and not a variable). Open the supplementary code window and add in the 'function implementations' part:
Code: Select all
#undef FCV_PI
#define FCV_PI 3.1415926535897932384626433832795028841971
This will redefine the constant using full double-precision when compiled. You can do this for any other variables created as constants - but not for variables themselves.
If your PI is already defined and used as a variable open the project explorer window, right click on the PI variable and select 'Convert to constant' from the menu.
As far as the LUT goes, if this is an issue I suspect the C compiler is truncating the values - that is a lot of digits and a binary floating point number is not 100% accurate. Try appending 'l' to your constants to specifically say they are 'long doubles', eg: 3.141......1971L
However, as a side note I have used purely 8 and 12 bit fixed point integers to create a fully working 3D engine before with no problems, so accuracy may not be the main cause of errors - ensure you are not introducing compound error by continuously multiplying by floats such as PI or your calculations will drift eventually no matter how many digits you add.
I hope this helps,
Jonny
Re: Truncated floating point numbers
Posted: Wed Jul 18, 2012 4:43 pm
by Mantas
Hello Jonny,
You are as always helpful, thanks

I think the 15 digit precision for variables will be sufficient. I will give it a try with the redefined constant PI. When are you planing to release the update?
Best regards,
Mantas
Re: Truncated floating point numbers
Posted: Sun Jul 22, 2012 9:37 am
by Mantas
Hello Jonny,
So I have tried a few things:
I have created a LUT such as:
Code: Select all
const double B_TERMS[B_COUNT][B_MAX_SUBCOUNT][TERM_COUNT]=
{
{
{280.0,3.199,84334.662},
{102.0,5.422,5507.553},
{80,3.88,5223.69},
{44,3.7,2352.87},
{32,4,1577.34}
},
{
{9,3.9,5507.55},
{6,1.73,5223.69}
}
};
Then I created a macro with a C code to get the values from the LUT and display this on an LCD. I have tried displaying it with a gcvt function, and with float to integer macro, just to make sure both are the same and gcvt function is not introducing some errors. But the results were the same. For example i was trying to display the value 5507.55 but I was receiving value of 5507.5498. Then I have tried storing a the same value but multiplied by 10pow6 (5507550000) and later divide the value by the same 10pow6 to see if this made any changes. Unfortunately I received a value of 5507.5502 . I remember Sean mentioned the possibility of rounding errors in his article about the lookup tables, here is the quote:
Hello,
Yes, it is possible to change the array data type to suit the range of the data values being stored. The Flowcode variables used to handle the data (including the table reader macro return variable) will also need to be changed to match the selected data type.
The C data types that are directly compatible with Flowcode depend on the version of Flowcode being used. In the case of Flowcode for ARM, a 'Float' variable is compatible with a C 'double' variable.
The use of floating point variables introduces the possibility of rounding errors, but some of your example values are too large for the 'int' option.
So the question stands, what to do to avoid this? Any Ideas?
I have also added just an example the amount of error I get due to this imperfection in my calculations on the ARM.
Best regards,
Mantas
Re: Truncated floating point numbers
Posted: Mon Jul 23, 2012 7:42 am
by Mantas
Good morning,
I made some observations:
value stored / value returned / difference
5507.553 / 5507.5532 / +0.0002
3.199 / 3.1989 / -0.0001
5.422 / 5.4219 / -0.0001
5223.69 / 5223.6899 /-0.0001
2352.87 / 252.8701 / +0.0001
84334.662 / 84334.664 / +0.002
Still not letting my hands down! Looking for a way to store without these errors...
Best regards,
Mantas
Re: Truncated floating point numbers
Posted: Mon Jul 23, 2012 7:55 am
by Mantas
Ok, it looks like it is something with 6 digit precision. I tried storing number 5507553000.0, returned the value and used the fround(value,0) to round the fraction to 0 after that I divided it by 1000000.0, and I expected to receive the value of 5507.5530, but I received 5507.552768. Then I tried returning the value without division, and I received 5507552768, so as I can see, every value up to a sixth digit in this case is correct, but this does not explain why 3.199 is returned 3.1989...I am puzzled
Best regards,
Mantas
Re: Truncated floating point numbers
Posted: Mon Jul 23, 2012 9:02 am
by JonnyW
Good morning.
The problem with floating point numbers is powers of 2. A floating point number has to represent 1/N as a binary value. However in binary any number N which is not a power of 2 has a recurring reciprocal, leading to inaccuracies.
For example, try in your tests both 0.25 and 0.2.
The 0.25 is 1/4, which is a power of 2, so is accurate. The 0.2 is 1/5 which is not a power of 2, hence it is inaccurate. The trick with floats is to ensure that you are not repeatedly multiplying or dividing them together - this leads to rounding errors.
As an example think of the following two loops, which do the same thing:
Code: Select all
for increment = 1 to max
value = value + 0.1
next
Code: Select all
for increment = 1 to max
value = (0.1 * increment) / max
next
On exit 'value' should be (0.1 * max) in both cases, but in the first case it wont be due to compound error - 0.1 is not an exact floating point number. However in the second case it will be accurate, because the error is not accumulated through the loop.
I'm sorry if this is a little rambling, but I hope you get what I mean.
EDIT: Have a look at the Wikipedia on floats:
http://en.wikipedia.org/wiki/Floating_p ... d_rounding
It explains things better than I can.
Jonny
Re: Truncated floating point numbers
Posted: Mon Jul 23, 2012 12:31 pm
by Mantas
So I've read the whole article, thanks. It was a little bit complicated to understand in non native language, but I think I've got the point. As far as I understand it all comes down to number of digits of precision. Should this improve after you release the update which ups it to 15 digits?
Best regards,
Mantas
Re: Truncated floating point numbers
Posted: Mon Jul 23, 2012 1:11 pm
by JonnyW
Hello. Yeah, it can be tricky to get your head round - I wouldn't have a chance in a non-native language!
As far as I understand it all comes down to number of digits of precision
Yes and no - the number of digits matters, of course, but only up to a point. 6 decimal digits gives you accuracy of 1 part in a million, which is usually enough. A single-precision float can only work up to 1 in about 16-million anyway.
Think about the number 1/3 in decimal. This is 0.333333333.....33333. It doesn't matter how many threes we add to the end it will never be accurate because the fraction goes on for ever, so it can never be accurate. The same applies to floats - any number you write down which is not a power of 2 is just an approximation. Because PI is irrational, it is a prime example of something that will never be accurate.
That said, double-width precision should help. I can't guarantee that the 15-digit update will change anything but I hope so. You can try this before the release using the code customisation per-icon and supplementary code.
However, if you are already writing this code directly in C using 'double' and it is not accurate enough I doubt there will be much you can do to sort this - it may be GCC that is truncating the values. There are ways round this but they are not nice at all and I would recommend trying to figure out ways to code your program without needing super-accurate numbers which you will never really get using floats.
Out of interest what is it you are doing that needs such accuracy?
Jonny
Re: Truncated floating point numbers
Posted: Mon Jul 23, 2012 4:11 pm
by Mantas
Hello Jonny,
Actually I have the complete C code for that and Using Code::Blocks it compiles it to an executable program and it is very precise up to 6 digits after the point. This software I am trying to implement on the arm chip is for Solar Position Algorithm, based on astronomical almanac theory, so it could track the suns position up to 0.0003 degrees precision, without any sensors, just the GPS data, like time and geographical position. I have all the software translated to the flowcode, and it working, just the precision with these first calculation steps is producing totally unacceptable results, like solar position +- >120 degrees...Actually I had this software written on flowcode v4 without using the LUT, but using the IF blocks...and as you already saw the LUT stores a lot of numbers, and the code was huge, and adding function like gcvt() caused the program to balloon out of chips memory range (but it was precise). That's why I decided to rewrite the program from the base on V5 to optimize it, but now I have this problem, and it is very frustrating
Could you tell me a little bit more about this:
You can try this before the release using the code customisation per-icon and supplementary code.
Best regards,
Mantas
Re: Truncated floating point numbers
Posted: Tue Jul 24, 2012 11:12 am
by JonnyW
Hi Mantas.
No probs. If you right click on any icon in v5 you should see a 'Customize C code...' option. This will allow you to modify the C code behind any icon directly. Clicking the 'Revert' in this edit window will put the icon back to normal.
This code is passed direct to the compiler but simulation will behave as though the icon is not modified. I find this useful on occasion to make the simulation do one thing and the downloaded code do another.
Jonny