Does ruby calculate floats wrong? [duplicate] - ruby

This question already has answers here:
Addition error with ruby-1.9.2 [duplicate]
(2 answers)
Closed 4 years ago.
Whats wrong here? (ruby version: 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.0.0]
x = 523.8
w = 46.9
xm = x + w
assert_equal w, (xm - x) # FAILS with: <46.9> expected but was <46.89999999999998>

From The Floating-Point Guide:
Why don’t my numbers, like 0.1 + 0.2 add up to a nice round 0.3, and
instead I get a weird result like 0.30000000000000004?
Because internally, computers use a format (binary floating-point)
that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all.
When the code is compiled or interpreted, your “0.1” is already
rounded to the nearest number in that format, which results in a small
rounding error even before the calculation happens.
Read the linked-to site for details and ways to get around this.

This is perfectly normal; it is a fact about the lower-level concept of floating point arithmetic rather than Ruby and therefore can occur in any language.
Floating point arithmetic is not exact. Equality should be replaced with closeness along the lines of assert((xm-x).abs < epsilon), where epsilon is some small number like 0.01.

Read this. It describes the way binary representation of floating point numbers work in every language, not just Ruby.

The answer to your question is: No.
(Other answers tell you why, but you didn't ask that. :p)

Related

floating point error in Ruby's BigDecimal class? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
The universal advice to avoid floating point errors in ruby is to use BigDecimal. I must be overlooking something, because I think I've found a case where BigDecimal math is returning an error where a Float does not:
using Float gives the correct answer of 2.75:
> 50.0 * 0.6 / 360.0 * 33
=> 2.75
using BigDecimal gives the incorrect answer of 2.74999999:
> BigDecimal("50") * BigDecimal("0.6") / BigDecimal("360") * BigDecimal("33")
=> #<BigDecimal:7efe74824c80,'0.2749999999 999999989E1',27(36)>
Someone please tell me what I'm missing here?
Let's simplify your example, and use this one instead:
BigDecimal(1) / BigDecimal(3) * BigDecimal(3)
# => #<BigDecimal:19289d8,'0.9999999999 99999999E0',18(36)>
How did it get there?
BigDecimal(1) / BigDecimal(3)
# => #<BigDecimal:1921a70,'0.3333333333 33333333E0',18(36)>
BigDecimal does not provide rational numbers, so when you divide 1 by 3, you get 0, following by a lot of 3s. A lot, but not infinitely many. When you then multiply that by 3, you will get 0 followed by equally many 9s.
I believe you misread the BigDecimal's advertisement (although I am not sure it is anywhere advertised as the solution to floating point errors). It just provides arbitrary precision. It is still a floating point number. If you really want exact numbers when dividing numbers, you might take a look at Rational class:
(Rational(50) * Rational(0.6) / Rational(360) * Rational(33)).to_f
# => 2.75

ruby issue with float point iteration [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 7 years ago.
When I run the code
count = 0
while count < 1
count += 0.1
puts count
end
I would expect
0.1
0.2
0.3
. . .
I have however been getting
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
1.0999999999999999
can anyone help explain this?
Think of it this way:
Your computer only has 32 or 64 bits to represent a number. That means it can only represent a finite amount of numbers.
Now consider all the decimal values between 0 and 1. There is an infinite amount of them. How can you possibly represent all Real Numbers if your machine can't even represent all the numbers between 0 and 1?
The answer is that your machine needs to approximate decimal numbers. This is what you are seeing.
Of course there are libraries that try to overcome these limitations and make it so that you can still accurately represent decimal numbers. One such library is BigDecimal:
require 'bigdecimal'
count = BigDecimal.new("0")
while count < 1
count += 0.1
puts count.to_s('F')
end
The downfall is that these libraries are generally slower at arithmetic, because they are a software layer above the CPU doing these calculations.
Floating-point numbers cannot precisely represent all real numbers, and floating-point operations cannot precisely represent true arithmetic operations, this leads to many surprising situations.
I advise to read: https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
You may want to use BigDecimal to avoid such problems.
This is one of the many consequences of the representation of floating point number in memory !
To explain what exactly is is happening would be very long, and has other people have already done it better before, the best thing for you would be to read about go read about it elsewhere :
The very good What Every Computer Scientist Should Know About Floating-Point Arithmetic (article from 1991, reprint on oracle)
Wikipedia pages Floating point and IEEE floating point
IEEE 754 References
You can also have a look at those previous questions on SO:
What is a simple example of floating point/rounding error?
Ruby BigDecimal sanity check (floating point newb)
Strange output when using float instead of double

Why does ruby round like this? [duplicate]

This question already has answers here:
Why is division in Ruby returning an integer instead of decimal value?
(7 answers)
Closed 8 years ago.
Hi I have the following question:
When I put (1+7/100) in ruby it gives 1.
This is very strange because normally this is how I calculate a 7% increase in Excel.
But when I put (1+7.0/100) it gives me 1.07 which is the correct answer I expected.
Why is ruby doing this? And how do you solve this issue in your calculations in ruby?
This has nothing to do with rounding.
Ruby does division differently on float than it does on an integer.
If you divide integers, you will always get an integer result.
If you divide with floats (or a mixture of integer and float), you will always get a float result.
Remember your order of operations, too. Ruby is going to handle the division before it handles the addition.
7/100 = 0 so 1+0 = 1
7.0/100 = 0.07 so 1+0.07 = 1.07

Why does 55.0 / 1.1 equal 49.99999999999999? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why 6.84 - 3.6 == 3.2399999999999998
And by extension, why does 49.99999999999999 * 1.1 equal 55.0?
I assume this is do to with floating point arithmetic, but am somewhat perplexed as to why this occurs with such a simple sum, and why it is also true for the multiplication case.
You're correct, it is entirely to do with floating point arithmetic. Many decimal numbers are only representable to a certain accuracy in binary, which is why you see the behaviour here. This isn't restricted to ruby - I'd suggest reading What every computer scientist should know about floating point arithmetic.
Your computer works in binary, not in decimal. The number 1.1 cannot be exactly represented in a finite binary representation, so it is necessarily an approximation.

Ruby number precision with simple arithmetic

I'm learning Ruby for fun, and for creating websites also (but that's irrelevant). While playing with it, i noticed something "weird"
When I compute 4.21 + 5 with irb, it answers 9.21 (weird, right?)
when I compute 4.23 + 5, it gives 9.23 (waw, that's definitely weird).
and when i type 4.22 + 5, it answers 9.21999... (w...wait! that's really weird).
Hence my question: what's going on?
I'd understand this behavior with division or really big numbers, but in this simple case....???
Does it mean that i can't develop an accounting app with Ruby?
Is there a patch or something to be applied? (to my brains, most likely)
You should read up on floating point representation in computers. This guide is a good place to start. Here's the short of it:
Because internally, computers use a
format (binary floating-point) that
cannot accurately represent a number
like 0.1, 0.2 or 0.3 at all.
When the code is compiled or
interpreted, your “0.1” is already
rounded to the nearest number in that
format, which results in a small
rounding error even before the
calculation happens.
By the way, I'm not sure why you think 4.21 + 5 = 9.21 or 4.23 + 5 = 9.23 is weird. If you think it's weird because one literal is an integer and one is a float, which ends up as a float response, that's how Ruby and some other languages handle differences in number types. It wouldn't be handy if Ruby dropped your float's precision and gave you just an integer back (9), so any integer literals are effectively changed to floats.
As for using floating-point numbers in a financial application, check out Developing financial application. The main takeaway is use the Decimal object vs. Float.
http://ruby-decimal.rubyforge.org/
This is the package you'd want to do reliable Floating Point maths in ruby. The Developint Financial Applications link doesn't reference it, but it makes the important point of using Decimal data types in your database.
Just noting this since it was non obvious for me :)

Resources