- Post Reply Bookmark Topic Watch Topic
- New Topic

programming forums
Java
Mobile
Certification
Databases
Caching
Books
Engineering
Micro Controllers
OS
Languages
Paradigms
IDEs
Build Tools
Frameworks
Application Servers
Open Source
This Site
Careers
Other
all forums

this forum made possible by our volunteer staff, including ...

Marshals:

- Campbell Ritchie
- Bear Bibeault
- Devaka Cooray
- Liutauras Vilda
- Jeanne Boyarsky

Sheriffs:

- Knute Snortum
- Junilu Lacar
- paul wheaton

Saloon Keepers:

- Ganesh Patekar
- Frits Walraven
- Tim Moores
- Ron McLeod
- Carey Brown

Bartenders:

- Stephan van Hulst
- salvin francis
- Tim Holloway

posted 13 years ago

Hi all

I was playing with some primitive casting, like so:

public class Test {

public static void main(String[] args) {

float f = (float)99.9;

double d1 = 99.9;

double d2 = f;

System.out.println("f: " + f);

System.out.println("d1: " + d1);

System.out.println("d2: " + d2);

}

}

Here's the output:

99.9

f: 99.9

d1: 99.9

d2: 99.9000015258789

I'd be *very* grateful if someone could explain to me why d2 seems to be greater than d1 (I know its not much, but don't understand why!).

Ta

Tony

I was playing with some primitive casting, like so:

public class Test {

public static void main(String[] args) {

float f = (float)99.9;

double d1 = 99.9;

double d2 = f;

System.out.println("f: " + f);

System.out.println("d1: " + d1);

System.out.println("d2: " + d2);

}

}

Here's the output:

99.9

f: 99.9

d1: 99.9

d2: 99.9000015258789

I'd be *very* grateful if someone could explain to me why d2 seems to be greater than d1 (I know its not much, but don't understand why!).

Ta

Tony

posted 13 years ago

you might want to read this paper.

in short, floating-point types like "float" and "double" are never exact; they are only approximations of the number you want. the differences between the number you want and the number you get, with these types, are complex and detailed, but can be considered more or less random, at least as a rule of thumb.

moreover, the differently-sized floating point types (float versus double, in your case) are inexact in*different ways*. "double" has more power to represent more decimal places — or to represent larger numbers without dropping low-order digits — but there's not necessarily any one-to-one correspondence between the numbers a "float" can represent and those that "double" can represent, and the inaccuracies each format will introduce are different too.

this is just a fact of life when using floating-point numbers. if it's simply not acceptable, either use rounding methods to your desired number of decimal points, or find a way to make do with integers alone.

in short, floating-point types like "float" and "double" are never exact; they are only approximations of the number you want. the differences between the number you want and the number you get, with these types, are complex and detailed, but can be considered more or less random, at least as a rule of thumb.

moreover, the differently-sized floating point types (float versus double, in your case) are inexact in

this is just a fact of life when using floating-point numbers. if it's simply not acceptable, either use rounding methods to your desired number of decimal points, or find a way to make do with integers alone.

posted 13 years ago

Well, that's not *totally* true - 0.5 for example can always be presented exactly, as well as 0.25, 0.75 ...

The point is that float and double use the binary system, whereas your literals are written in the decimal system. Not all finite decimal numbers translate to finite binary numbers, though. 0.1, for example, becomes an infinite number in the binary system! Because both float and double have to stop somewhere, but double uses higher precision, a 0.1d is a little bit bigger than a 0.1f...

As a similar example, consider how the ternary number 0.1 (= 3^-1 = 1/3) becomes an infinite number when translated to the decimal system.

Originally posted by M Beck:

in short, floating-point types like "float" and "double" are never exact; they are only approximations of the number you want.

Well, that's not *totally* true - 0.5 for example can always be presented exactly, as well as 0.25, 0.75 ...

The point is that float and double use the binary system, whereas your literals are written in the decimal system. Not all finite decimal numbers translate to finite binary numbers, though. 0.1, for example, becomes an infinite number in the binary system! Because both float and double have to stop somewhere, but double uses higher precision, a 0.1d is a little bit bigger than a 0.1f...

As a similar example, consider how the ternary number 0.1 (= 3^-1 = 1/3) becomes an infinite number when translated to the decimal system.

The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus

M Beck

Ranch Hand

Posts: 323

posted 13 years ago

very true. but more to the original poster's point, even though double has higher precision than float, it's not necessarily a superset of float — there may be (and probably are) many numbers that "float" can represent exactly yet double can only approximate.

to make a long story short, the problem mr. Walters was seeing stems from a floating-point conversion operation. when a float is cast to a double, the implicit conversion — like any other operation on floating-point numbers, really — always runs a risk of rounding error, introducing inaccuracy. frankly, i'm surprised that a double declared from a constant doesn't also reduce to the same inaccurate approximation as the double cast from a float. i can only assume that the compiler uses a different conversion method when reading constants from source code than the JVM uses when casting variables at run-time. which is odd, but i've seen odder...

to make a long story short, the problem mr. Walters was seeing stems from a floating-point conversion operation. when a float is cast to a double, the implicit conversion — like any other operation on floating-point numbers, really — always runs a risk of rounding error, introducing inaccuracy. frankly, i'm surprised that a double declared from a constant doesn't also reduce to the same inaccurate approximation as the double cast from a float. i can only assume that the compiler uses a different conversion method when reading constants from source code than the JVM uses when casting variables at run-time. which is odd, but i've seen odder...

posted 13 years ago

Mathematically it's indeed not totally true, but in the context of computer floating point mathematics in computers using a discrete system of representing data it is

Originally posted by Ilja Preuss:

Well, that's not *totally* true - 0.5 for example can always be presented exactly, as well as 0.25, 0.75 ...

Mathematically it's indeed not totally true, but in the context of computer floating point mathematics in computers using a discrete system of representing data it is

42

Tony Walters

Ranch Hand

Posts: 54

posted 13 years ago

Thanks guys. That one really stumped me. I've been using Java (a lot) for 5 years or so, but never come across that. Simple when explained really.

Ta

Tony

Ta

Tony

Ilja Preuss

author

Posts: 14112

posted 13 years ago

Sorry, I don't understand this. Are you saying that there are no values that can be represented exactly by IEEE floating point numbers? That sounds obviously wrong to me...
The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus

Originally posted by Jeroen Wenting:

Mathematically it's indeed not totally true, but in the context of computer floating point mathematics in computers using a discrete system of representing data it is

Sorry, I don't understand this. Are you saying that there are no values that can be represented exactly by IEEE floating point numbers? That sounds obviously wrong to me...

Ilja Preuss

author

Posts: 14112

posted 13 years ago

As far as I know, it does. It's just that Java "knows" that the internal representation is inaccurate, and therefore manages to conceal it to some amount when printing to the console.

Try the following code:

The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus

Originally posted by M Beck:

i'm surprised that a double declared from a constant doesn't also reduce to the same inaccurate approximation as the double cast from a float.

As far as I know, it does. It's just that Java "knows" that the internal representation is inaccurate, and therefore manages to conceal it to some amount when printing to the console.

Try the following code:

Jeroen Wenting

Ranch Hand

Posts: 5093

posted 13 years ago

There are no floating point numbers that can be guaranteed to be represented without rounding errors.

A binary system doesn't care whether something is a "nice" fracture after all. 2463/4235327 is a nice fracture yet I doubt 0.0010936581756261086806284378986558 (which was calculated using a PC based calculator) can be guaranteed to be without rounding errors.

1/2 will usually (probably in 99.999999999% of cases) deliver 0.5000000000000000 but in that last case it may produce 0.49999999999999994 instead. Now if the viewer wanted to see that result to a higher precision than that he'd get an unexpected result.

A binary system doesn't care whether something is a "nice" fracture after all. 2463/4235327 is a nice fracture yet I doubt 0.0010936581756261086806284378986558 (which was calculated using a PC based calculator) can be guaranteed to be without rounding errors.

1/2 will usually (probably in 99.999999999% of cases) deliver 0.5000000000000000 but in that last case it may produce 0.49999999999999994 instead. Now if the viewer wanted to see that result to a higher precision than that he'd get an unexpected result.

42

Ilja Preuss

author

Posts: 14112

posted 13 years ago

Of course there are. A float is just a number of bits that represent a number, and all numbers that can be represented using those bits are, of course, represented without "rounding errors". Wether those numbers can be represented in the decimal system using a finite representation is a different question - and that can certainly be answered with "yes" for some of the possible values.

I didn't say that it does.

Which doesn't prove at all that there are *no* numbers at all that can be guaranteed to be without rounding errors.

1/2 is 0.1 binary. I'd think that there is a float bit pattern that *exactly* represents this value. And I'd assume that Java deterministically uses that exact value for literal values of 0.5f.

Of course that doesn't mean that *every computation* that theoretically should result in 1/2 ends up with that exact bit pattern. Is that what you were referring to?
The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus

Originally posted by Jeroen Wenting:

There are no floating point numbers that can be guaranteed to be represented without rounding errors.

Of course there are. A float is just a number of bits that represent a number, and all numbers that can be represented using those bits are, of course, represented without "rounding errors". Wether those numbers can be represented in the decimal system using a finite representation is a different question - and that can certainly be answered with "yes" for some of the possible values.

A binary system doesn't care whether something is a "nice" fracture after all.

I didn't say that it does.

2463/4235327 is a nice fracture yet I doubt 0.0010936581756261086806284378986558 (which was calculated using a PC based calculator) can be guaranteed to be without rounding errors.

Which doesn't prove at all that there are *no* numbers at all that can be guaranteed to be without rounding errors.

1/2 will usually (probably in 99.999999999% of cases) deliver 0.5000000000000000 but in that last case it may produce 0.49999999999999994 instead.

1/2 is 0.1 binary. I'd think that there is a float bit pattern that *exactly* represents this value. And I'd assume that Java deterministically uses that exact value for literal values of 0.5f.

Of course that doesn't mean that *every computation* that theoretically should result in 1/2 ends up with that exact bit pattern. Is that what you were referring to?

- Post Reply Bookmark Topic Watch Topic
- New Topic

Boost this thread!