David Dickinson

Ranch Hand

Posts: 66

posted 12 years ago

Hi All,

I've searched the archive and found a few different posts regarding restricting the number of decimal places in doubles. However they all suggest different methods, BigDecimal, NumberFormat etc.

Which is the simplest method of rounding a number say 10.023445656 to 10.02?

Thanks

I've searched the archive and found a few different posts regarding restricting the number of decimal places in doubles. However they all suggest different methods, BigDecimal, NumberFormat etc.

Which is the simplest method of rounding a number say 10.023445656 to 10.02?

Thanks

Peter Chase

Ranch Hand

Posts: 1970

posted 12 years ago

No, that's not a good way to do it. The reason is that floating-point arithmetic ("double" is a floating-point type) is not exact. So you're quite likely to end up printing something like 10.020000000000001 or 10.0199999999999 .

NumberFormat is probably the way to go. Alternatively, you could switch to using integers, where arithmetic is exact. Obviously, that would involve rescaling your values, as you can't have fractions.

Currency calculations are an example. Beginners often do currency calculations in floating-point, because they work in dollars, pounds or euros, which have a fractional part - the number of cents or pence. Instead, such calculations should be done in cents or pence, by integers. When printing out, use the divide (/100) and modulus (%100) integer operations to get the number of dollars/pounds/euros and cents/pence respectively.

HTH

Originally posted by Joyce Lee:

How about this?

No, that's not a good way to do it. The reason is that floating-point arithmetic ("double" is a floating-point type) is not exact. So you're quite likely to end up printing something like 10.020000000000001 or 10.0199999999999 .

NumberFormat is probably the way to go. Alternatively, you could switch to using integers, where arithmetic is exact. Obviously, that would involve rescaling your values, as you can't have fractions.

Currency calculations are an example. Beginners often do currency calculations in floating-point, because they work in dollars, pounds or euros, which have a fractional part - the number of cents or pence. Instead, such calculations should be done in cents or pence, by integers. When printing out, use the divide (/100) and modulus (%100) integer operations to get the number of dollars/pounds/euros and cents/pence respectively.

HTH

Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.

David Dickinson

Ranch Hand

Posts: 66

posted 12 years ago

Hi,

Is there no way to round the double but keep the the value stored as a double?

I'm running JUnit tests and want to compare the computed result with the result I have calculated manually which is stored to two decimal points?

Thanks

Is there no way to round the double but keep the the value stored as a double?

I'm running JUnit tests and want to compare the computed result with the result I have calculated manually which is stored to two decimal points?

Thanks

Mike Gershman

Ranch Hand

Posts: 1272

David Dickinson

Ranch Hand

Posts: 66

posted 12 years ago

If I can't find a more elegant solution to the problem then thats an option Mike.

This doesn't seem like a big problem to me surely Java has some function which automatically rounds a number when a precision of 2 is required?

Thanks all, hopefully i'll get a solution soon

This doesn't seem like a big problem to me surely Java has some function which automatically rounds a number when a precision of 2 is required?

Thanks all, hopefully i'll get a solution soon

Joyce Lee

Ranch Hand

Posts: 1392

posted 12 years ago

Peter, I printed the output using the Math.round approach. But it didn't end up printing like 10.020000000000001 or 10.0199999999999. I may have missed out something. Could you give a value that would end up something like that? Thanks.

Originally posted by Peter Chase:

No, that's not a good way to do it. The reason is that floating-point arithmetic ("double" is a floating-point type) is not exact. So you're quite likely to end up printing something like 10.020000000000001 or 10.0199999999999 .

Peter, I printed the output using the Math.round approach. But it didn't end up printing like 10.020000000000001 or 10.0199999999999. I may have missed out something. Could you give a value that would end up something like that? Thanks.

Mike Gershman

Ranch Hand

Posts: 1272

Layne Lund

Ranch Hand

Posts: 3061

posted 12 years ago

Since you are using JUnit, there is no reason to round. Instead, you should use Assert.assertEquals(double expected, double actual, double precision) to compare the two numbers. The last parameter indicates the accuracy of your comparison. For example, you can do something like

To assert that your calculated value is within 1/100 th of the manually derived value.

For more details about the methods available in the Assert class (and other JUnit classes, you should consult the JUnit javadocs. They come with the JUnit distribution.

HTH

Layne

[ November 19, 2004: Message edited by: Layne Lund ]

To assert that your calculated value is within 1/100 th of the manually derived value.

For more details about the methods available in the Assert class (and other JUnit classes, you should consult the JUnit javadocs. They come with the JUnit distribution.

HTH

Layne

[ November 19, 2004: Message edited by: Layne Lund ]

Layne Lund

Ranch Hand

Posts: 3061

posted 12 years ago

I think this was an illustrative example. Results can vary between machines. The point is that floating point arithmetic is not exact because of the limitations of storing fractions in a computer. This is very analogous to writing one-third (1/3) as a decimal. Depending on how accurate you want to be, this fraction can be written as 0.33 or 0.3333, but no matter what you do, there is no exact decimal equivalent to 1/3. Similar situations arise with floating point numbers stored in binary. I won't get into the details here because it has been discussed several times before. If you are interested in the details, you can use the Saloon's search tool or google for more information.

Layne

Originally posted by Joyce Lee:

Peter, I printed the output using the Math.round approach. But it didn't end up printing like 10.020000000000001 or 10.0199999999999. I may have missed out something. Could you give a value that would end up something like that? Thanks.

I think this was an illustrative example. Results can vary between machines. The point is that floating point arithmetic is not exact because of the limitations of storing fractions in a computer. This is very analogous to writing one-third (1/3) as a decimal. Depending on how accurate you want to be, this fraction can be written as 0.33 or 0.3333, but no matter what you do, there is no exact decimal equivalent to 1/3. Similar situations arise with floating point numbers stored in binary. I won't get into the details here because it has been discussed several times before. If you are interested in the details, you can use the Saloon's search tool or google for more information.

Layne

David Dickinson

Ranch Hand

Posts: 66

posted 12 years ago

Layne,

Indeed your right I have always set my Delta (the allowable difference between the two numbers under evaluation) to 0 to ensure accuracy. But this would be the simplest way of doing things.

That old saying "I can't see for things for looking at them" springs to mind

Thank you!

Indeed your right I have always set my Delta (the allowable difference between the two numbers under evaluation) to 0 to ensure accuracy. But this would be the simplest way of doing things.

That old saying "I can't see for things for looking at them" springs to mind

Thank you!

Joyce Lee

Ranch Hand

Posts: 1392

posted 12 years ago

I still don't get the idea why using Math.round approach would end up 10.020000000000001 or 10.0199999999999. I did a quick search in this forum. Here are the threads that recommended using Math.round approach to round off to 2 decimal places. Did I miss out anything?

Thread 1

Thread 2

Thread 3

Thread 4

Thread 5

Thread 1

Thread 2

Thread 3

Thread 4

Thread 5

Layne Lund

Ranch Hand

Posts: 3061

posted 12 years ago

As you probably see, you shouldn't rely on comparing doubles for equalit (which is essentially the same as setting your delta to 0.0 in this case). The reasons are related to another reply I will post next, so stay tuned.

Layne

Originally posted by David Dickinson:

Layne,

Indeed your right I have always set my Delta (the allowable difference between the two numbers under evaluation) to 0 to ensure accuracy. But this would be the simplest way of doing things.

That old saying "I can't see for things for looking at them" springs to mind

Thank you!

As you probably see, you shouldn't rely on comparing doubles for equalit (which is essentially the same as setting your delta to 0.0 in this case). The reasons are related to another reply I will post next, so stay tuned.

Layne

Layne Lund

Ranch Hand

Posts: 3061

posted 12 years ago

The problem isn't with Math.round(); it's with doing arithmetic on the result that is returned from this method! The problem here stems from how most modern computers store floating point numbers (double is a floating-point number). This thread gives a basic explanation of the issues involved here. For more technical details, you need to look at the IEEE standard that is mentioned in the last message of the thread. (Take a look here for more information about IEEE 754 standard. Although it doesn't give details about the issues discussed here, the concpets discussed are necessary to understand the implications of floating-point arithmetic.)

HTH

Layne

[ November 19, 2004: Message edited by: Layne Lund ]

Originally posted by Joyce Lee:

I still don't get the idea why using Math.round approach would end up 10.020000000000001 or 10.0199999999999. I did a quick search in this forum. Here are the threads that recommended using Math.round approach to round off to 2 decimal places. Did I miss out anything?

Thread 1

Thread 2

Thread 3

Thread 4

Thread 5

The problem isn't with Math.round(); it's with doing arithmetic on the result that is returned from this method! The problem here stems from how most modern computers store floating point numbers (double is a floating-point number). This thread gives a basic explanation of the issues involved here. For more technical details, you need to look at the IEEE standard that is mentioned in the last message of the thread. (Take a look here for more information about IEEE 754 standard. Although it doesn't give details about the issues discussed here, the concpets discussed are necessary to understand the implications of floating-point arithmetic.)

HTH

Layne

[ November 19, 2004: Message edited by: Layne Lund ]

Joyce Lee

Ranch Hand

Posts: 1392

posted 12 years ago

I wasn't talking about Math.round(). I was referring to Math.round approach, meaning

I would appreciate if someone could give a value of x that would result in something like this 10.020000000000001 instead of two decimal places using the formula above. I tested it on Window platform. I couldn't reproduce this problem as claimed. Thanks.

[ November 19, 2004: Message edited by: Joyce Lee ]

Originally posted by Layne Lund:

The problem isn't with Math.round(); it's with doing arithmetic on the result that is returned from this method!

I wasn't talking about Math.round(). I was referring to Math.round approach, meaning

**Math.round(100 * x) / 100d**as a whole.

I would appreciate if someone could give a value of x that would result in something like this 10.020000000000001 instead of two decimal places using the formula above. I tested it on Window platform. I couldn't reproduce this problem as claimed. Thanks.

[ November 19, 2004: Message edited by: Joyce Lee ]

It is sorta covered in the JavaRanch Style Guide. |