Java-Gaming.org Hi !
 Featured games (90) games approved by the League of Dukes Games in Showcase (754) Games in Android Showcase (229) games submitted by our members Games in WIP (842) games currently in development
 News: Read the Java Gaming Resources, or peek at the official Java tutorials
 Home Help Search Login Register
Pages: [1]
 ignore  |  Print
 Floating point error  (Read 3831 times) 0 Members and 1 Guest are viewing this topic.
ryanm

Senior Devvie

Projects: 1
Exp: 15 years

Used to be bleb

 « Posted 2005-05-10 07:56:03 »

This is something that's annoyed me for ages:
 1  2  3  4  5  6  7  8  9  10  11  12 `public class FPError{    public static void main( String[] args )    {        float f = 0.0f;        for( int i = 0; i < 10; i++ )        {            f += 0.1f;            System.out.println( f );        }    }}`

gives
 1  2  3  4  5  6  7  8  9  10 `0.10.20.30.40.50.60.700000050.80000010.90000011.0000001`

Where does this error come from? Is it really too much to ask that simple addition works?
shmoove

Junior Devvie

Doh!

 « Reply #1 - Posted 2005-05-10 08:11:52 »

It comes from the fact that numbers are stored in binary in a finite sequence of bytes. If you could only remember numbers in decimal notation with a predetermined amount of digits, you would see the same problem when you try to do things with amounts like 1/3:

 1  2  3  4  5 `// using 4 digits:1/3 = 0.333 (not bad)1/3 + 1/3 = 0.666 (still OK)1/3 + 1/3 + 1/3 = 0.999 (looks fine for now)1/3 + 1/3 + 1/3 + 1/3 = 1.332 (hey, wait a minute! shouldn't it be 1.333?)`

shmoove
ryanm

Senior Devvie

Projects: 1
Exp: 15 years

Used to be bleb

 « Reply #2 - Posted 2005-05-10 08:25:54 »

That sounds reasonable for fractions like 1/3, as you can't express that exactly no matter how many bytes are used.

But why for 0.6 and 0.1? AFAICS, there's no problem expressing them exactly in a 32-bit float.

Here's an even more concise test case:
 1  2  3  4  5  6  7  8  9  10  11 `public class FPError{    public static void main( String[] args )    {        float f = 0.1f + 0.6f;        if( f != 0.7f )        {            System.out.println( "wtf? " + f );        }    }}`

gives:
 1 `wtf? 0.70000005`
 Games published by our own members! Check 'em out!
Markus_Persson

JGO Wizard

Medals: 19
Projects: 19

Mojang Specifications

 « Reply #3 - Posted 2005-05-10 08:44:16 »

It has to do with what base you use for your numbers.
In base 3, 1/3 is expressed as exactly 0.1. No fractions.

In base 2 (binary), it becomes very tricky to exactly express 1/10. It's something like 0.0001100110...
I haven't worked out if it's infinitly long like 1/3 is in decimal (base 10), but I've got a feeling it just might be.

Play Minecraft!
ryanm

Senior Devvie

Projects: 1
Exp: 15 years

Used to be bleb

 « Reply #4 - Posted 2005-05-10 09:13:59 »

You've got a point there.
Quote
AFAICS, there's no problem expressing them exactly in a 32-bit float.
Apparently, AFAICS isn't terribly far

It appears there's nothing to be done except weep for the fact that a number commonly occuring in our decimal-based world is a pathological case for floating-point representation
Malohkan

Senior Devvie

while (true) System.out.println("WOO!!!!");

 « Reply #5 - Posted 2005-05-10 12:10:12 »

if you do have a big problem with it, you can use classes like BigFloat and such, right?

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
shmoove

Junior Devvie

Doh!

 « Reply #6 - Posted 2005-05-10 12:41:32 »

Or make your own RationalNumber class (unless you need irrational numbers, then you're screwed ).

shmoove
Jeff

JGO Coder

Got any cats?

 « Reply #7 - Posted 2005-05-10 18:46:49 »

Yo uwant to have even more floating point fun?

How many starts does this method print?

 1  2  3  4  5  6  7 `public method printStars(float start){    float end  = start + 100;    while (start++

The answer is its indeterminate and based on the value of start.
Because floats are an aproximation whose accuracy changes with
the value, if start is high enough start++ becomes a nop lost iin
the rounding and its an idiot loop!

For this reason i personally believe that allowing ++ on floats was a syntactic error on the part of the original Java designers.

Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
Markus_Persson

JGO Wizard

Medals: 19
Projects: 19

Mojang Specifications

 « Reply #8 - Posted 2005-05-11 06:57:53 »

If so, +=1 shouldn't be allowed on floats either, since it'll fail for very large floats.

I guess it boils down to if you read i++ as "next" or as "+=1"

Play Minecraft!
digitprop

Junior Devvie

 « Reply #9 - Posted 2005-05-11 08:17:43 »

This is probably just a problem of internal representation vs. output / formatting. Just keep in mind that the internal representation is much more precise than you need your output to be (in most cases, that is; if not, then using float/double primitives is a bad idea anyway).

For example, this works nicely:

 1  2  3  4  5  6  7  8  9  10  11 `public static void main(String[] args){      NumberFormat nf=new DecimalFormat("0.00");            float f = 0.0f;      for (int i = 0; i < 10; i++)      {            f += 0.1f;            System.out.println(nf.format(f));      }}`

M. Fischer . www.digitprop.com
 Games published by our own members! Check 'em out!
Jeff

JGO Coder

Got any cats?

 « Reply #10 - Posted 2005-05-11 19:36:27 »

Quote
If so, +=1 shouldn't be allowed on floats either, since it'll fail for very large floats.

I guess it boils down to if you read i++ as "next" or as "+=1"

Yup good point.

To me though +1 is ana rtihmatic operation while ++ is an ordinal increment.

Maybe im just weird

Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
nonnus29

Senior Devvie

Giving Java a second chance after ludumdare fiasco

 « Reply #11 - Posted 2005-05-11 21:43:48 »

Quote
Where does this error come from? Is it really too much to ask that simple addition works?

You're laboring under some misapprehensions here;

1.  It's not an error
2.  It does work

This is how floating point numbers are defined to work.

The alternatives are fixed point and binary coded decimal.  Floating point is used more than these today because of faster implimitations in hardware and better general purpose flexibility.
Pages: [1]
 ignore  |  Print

 DesertCoockie (33 views) 2018-05-13 18:23:11 nelsongames (75 views) 2018-04-24 18:15:36 nelsongames (70 views) 2018-04-24 18:14:32 ivj94 (752 views) 2018-03-24 14:47:39 ivj94 (82 views) 2018-03-24 14:46:31 ivj94 (622 views) 2018-03-24 14:43:53 Solater (98 views) 2018-03-17 05:04:08 nelsongames (179 views) 2018-03-05 17:56:34 Gornova (405 views) 2018-03-02 22:15:33 buddyBro (1065 views) 2018-02-28 16:59:18
 Java Gaming Resourcesby philfrei2017-12-05 19:38:37Java Gaming Resourcesby philfrei2017-12-05 19:37:39Java Gaming Resourcesby philfrei2017-12-05 19:36:10Java Gaming Resourcesby philfrei2017-12-05 19:33:10List of Learning Resourcesby elect2017-03-13 14:05:44List of Learning Resourcesby elect2017-03-13 14:04:45SF/X Librariesby philfrei2017-03-02 08:45:19SF/X Librariesby philfrei2017-03-02 08:44:05
 java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org