Go Down

Topic: Unexpected output when converting to an integer with int() (Read 4805 times) previous topic - next topic

_mjw_


In general, it's best to avoid floats anywhere you can use integers.  For one, go browse the avr-libc handbook, particularly the math stuff.  You'll find a lot of it uses floats as parameters by default.  Since there's no floating-point hardware in an AVR mega or tiny, that all has to be done via software emulation, which is extra code bloat that you probably didn't need for your intended application.

Very interesting.  Will have to have a look at the avr-libc handbook.
Quote

For that reason, be aware of the math functions you use and try to implement them in more efficient ways if you can.  E.g., definitely use shifts to do powers of 2.  You'll get a more accurate result, it'll execute faster (a relative term), and assuming you don't use floats anywhere else, it'll save all the flash space required to include the fp math library.

Agreed.  Originally performed this calculation to get at each of the bits in a counter.  Using bitshift left (<<) or bitread() is more direct.
Quote

Naturally, when you need non-integer values and can't get by with fixed-point math, well ya godda do whatcha godda do.  And none of this applies in test cases and matters of curiosity like in this thread.

Yes, it is a matter of curiosity, but interesting enough to others also, I hope.

Coding Badly

#16
Dec 31, 2013, 02:31 am Last Edit: Dec 31, 2013, 02:41 am by Coding Badly Reason: 1
The following C code (OS X 10.8.5, gcc) produces expected output:
Could someone please explain why the Arduino produces different results?


Rounding.  These are the rules of interest...
http://en.wikipedia.org/wiki/IEEE_floating_point#Rounding_rules
In addition, Serial.print may use a rounding rule not on that list.

Which rule is used by your PC program?  Which rule is used by AVR Libc?  Which rule is used by the Arduino Run Time Library?  Is it possible your PC program is using a different rule than your Arduino program?


Or, intermediates...

Quote
Quote
32 bit float vs. 64 bit float

Recompiled with the option -m32 (to enforce 32 bit calculations) and got the same results!


Incorrect.  A modern 32 bit processor (like a Pentium) simply does not support operations on 32 bit floating point numbers.  They are capable of storing and loading 32 bit floats but all operations are done at 64 bits (or higher) to avoid problems with intermediate values.

MarkT


Quote

That's not unexpected at all.  All computers work that way.   

Not all.
The following C code (OS X 10.8.5, gcc) produces expected output:
Code: [Select]

#include <stdio.h>
#include <math.h>

main()
{
  int index, k, q;
  float m;
  for (k=0; k<=7; k++) {
    m = pow(2,k);
    q = (int) m;
    printf("m = %f",m);
    printf("\t q = %d\n",q);
  }
}

Here is the resulting output:

m = 1.000000    q = 1
m = 2.000000    q = 2
m = 4.000000    q = 4
m = 8.000000    q = 8
m = 16.000000   q = 16
m = 32.000000   q = 32
m = 64.000000   q = 64
m = 128.000000  q = 128

Could someone please explain why the Arduino produces different results?
Thank you!


Because floating point results are inexact, you cannot make assumptions like this.
Different implementations of pow, for instance, may special-case when the arguments
happen to be integral (on the Arduino there is no room for special cases, the standard
method using logarithms will be used with the expected imprecision in the LSBs)

To get integer powers of two you use the << operator.  1 << n
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

SirNickity

#18
Dec 31, 2013, 03:04 am Last Edit: Dec 31, 2013, 03:06 am by SirNickity Reason: 1
Because floating point results are inexact, you cannot make assumptions like this.


This is a profound point.  To any programmers that aren't already aware of the significance of this statement, it's something you'll want to read up on.

The gist is this:  Floating point values don't store exact values, they store approximations.  There are many integer values that can't be stored as floating point values, but will instead be just slightly off.  The implications of this are obvious for cumulative math -- and particular, code that deals with money.  Higher precision does not solve the root problem.  You may have 64 bits of precision, but all that means is you might get a whole bunch of .999999s when what you really wanted is .0.

(WOOHOO!  1000 posts.  And I am no longer a God member.  Edison outranks God?  Well, I guess they both said "Let there be light."  ;))

_mjw_


Because floating point results are inexact, you cannot make assumptions like this.
Different implementations of pow, for instance, may special-case when the arguments
happen to be integral (on the Arduino there is no room for special cases, the standard
method using logarithms will be used with the expected imprecision in the LSBs)
To get integer powers of two you use the << operator.  1 << n

Agreed.  Was also stated above.

Because floating point results are inexact, you cannot make assumptions like this.

This is a profound point.  To any programmers that aren't already aware of the significance of this statement, it's something you'll want to read up on.

Yes.  The arduino chip is using logarithms to calculate powers, and not many bits at that.  Those beyond the sixth after the decimal in the final result are often off.

Go Up