Truncated floating point numbers

For Flowcode users to discuss projects, flowcharts, and any other issues related to Flowcode 5.
To post in this forum you must have a registered copy of Flowcode 5 or higher.

Moderator: Benj

Post Reply
User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times

Truncated floating point numbers

Post 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 :!: :shock:
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
Science is my true religion.

User avatar
JonnyW
Posts: 1230
Joined: Fri Oct 29, 2010 9:13 am
Location: Matrix Multimedia Ltd
Has thanked: 63 times
Been thanked: 290 times
Contact:

Re: Truncated floating point numbers

Post 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

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times

Re: Truncated floating point numbers

Post by Mantas »

Hello Jonny,

You are as always helpful, thanks :wink: 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
Science is my true religion.

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times

Re: Truncated floating point numbers

Post 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.
ARM-SPA results.zip
ARM SPA compare
(9.66 KiB) Downloaded 285 times
Best regards,
Mantas
Attachments
test lut tolerance.c
Sample in flowcode
(14.76 KiB) Downloaded 258 times
Science is my true religion.

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times

Re: Truncated floating point numbers

Post 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
Science is my true religion.

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times

Re: Truncated floating point numbers

Post 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
Science is my true religion.

User avatar
JonnyW
Posts: 1230
Joined: Fri Oct 29, 2010 9:13 am
Location: Matrix Multimedia Ltd
Has thanked: 63 times
Been thanked: 290 times
Contact:

Re: Truncated floating point numbers

Post 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

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times

Re: Truncated floating point numbers

Post 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
Science is my true religion.

User avatar
JonnyW
Posts: 1230
Joined: Fri Oct 29, 2010 9:13 am
Location: Matrix Multimedia Ltd
Has thanked: 63 times
Been thanked: 290 times
Contact:

Re: Truncated floating point numbers

Post 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

User avatar
Mantas
Posts: 221
Joined: Tue May 15, 2012 10:32 pm
Location: Klaipeda, Lithuania - North sea, UK
Has thanked: 57 times
Been thanked: 27 times

Re: Truncated floating point numbers

Post 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
Science is my true religion.

User avatar
JonnyW
Posts: 1230
Joined: Fri Oct 29, 2010 9:13 am
Location: Matrix Multimedia Ltd
Has thanked: 63 times
Been thanked: 290 times
Contact:

Re: Truncated floating point numbers

Post 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

Post Reply