l = [1.0, 1.0, 2.0**0.5]
=> [1.0, 1.0, 1.4142135623731]s = l.map {|e| e**2}
=> [1.0, 1.0, 2.0]puts ‘foo’ if s[2] == s[1] + s[0]
=> nilputs ‘foo’ if 2.0 == 1.0 + 1.0
foo
=> nil
Does anyone know why s[2] == s[1] + s[0] is false ?
l = [1.0, 1.0, 2.0**0.5]
=> [1.0, 1.0, 1.4142135623731]s = l.map {|e| e**2}
=> [1.0, 1.0, 2.0]puts ‘foo’ if s[2] == s[1] + s[0]
=> nilputs ‘foo’ if 2.0 == 1.0 + 1.0
foo
=> nil
Does anyone know why s[2] == s[1] + s[0] is false ?
On 2 Jul 2008, at 12:30, Minh T. wrote:
Does anyone know why s[2] == s[1] + s[0] is false ?
If you check in IRB you’ll find that ((2.0 ** 0.5) ** 2.0) == 2.0
returns false. That will be due to rounding errors in performing the
sequence of floating point operations.
Ellie
raise ArgumentError unless @reality.responds_to? :reason
It still look odd as the value in s[2] is 2.0 which doesn’t seems to
have any rounding problem.
In any case is there any workaround to fix get the condition as true ?
Eleanor McHugh wrote:
On 2 Jul 2008, at 12:30, Minh T. wrote:
Does anyone know why s[2] == s[1] + s[0] is false ?
If you check in IRB you’ll find that ((2.0 ** 0.5) ** 2.0) == 2.0
returns false. That will be due to rounding errors in performing the
sequence of floating point operations.Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.netraise ArgumentError unless @reality.responds_to? :reason
On 2 Jul 2008, at 13:48, Minh T. wrote:
It still look odd as the value in s[2] is 2.0 which doesn’t seems to
have any rounding problem.In any case is there any workaround to fix get the condition as true ?
Floating point representations are in many cases (such as irrational
numbers like square root of 2) only approximations to a given value,
you therefore have to test that the value is accurate to a given
precision (number of significant digits). For example, given:
x = (1.0 + 1.0) ** 0.5
you could write your test as:
(x ** 2.0).between?(1.9999, 2.0001)
Ellie
raise ArgumentError unless @reality.responds_to? :reason
On 2 Jul 2008, at 14:25, Minh T. wrote:
It doesn’t look very elegant though to need such kind of hacking to
make
it base operator to work as expected.
And that method also imposes considerable runtime cost. As I said, use
a comparison such as (2.0).between?(1.99999, 2.00001) as that’s:
a. computationally much less expensive;
b. what a floating-point ‘==’ actually means.
Also you should probably read
and then do some further research into floating point number
representations to gain some deeper insight into what is actually
meant by 2.0 when it’s converted into binary format. It may inspire
you to more elegant ways of solving whatever problem it is that you’re
working on.
Ellie
raise ArgumentError unless @reality.responds_to? :reason
2008/7/2 Minh T. [email protected]:
I tried with
s = l.map {|e| (e**2).to_s.to_f}
instead of
s = l.map {|e| e**2}
and it now works.
But it works only accidentally! This is likely to break soon again.
It doesn’t look very elegant though to need such kind of hacking to make
it base operator to work as expected.
No, no, no! The operator works as expected. There is even an IEEE
standard defining how floating point math has to behave. You must
never rely on == when doing float math. In this case you rather
need to do either of these
resort to decimal math with BigDecimal
define equality as a max difference (“epsilon”) between two float
values and test that
Kind regards
robert
On 2 Jul 2008, at 15:01, Robert K. wrote:
resort to decimal math with BigDecimal
define equality as a max difference (“epsilon”) between two float
values and test that
Phrased much better than my replies
Ellie
raise ArgumentError unless @reality.responds_to? :reason
I tried with
s = l.map {|e| (e**2).to_s.to_f}
instead of
s = l.map {|e| e**2}
and it now works.
It doesn’t look very elegant though to need such kind of hacking to make
it base operator to work as expected.
Eleanor McHugh wrote:
On 2 Jul 2008, at 13:48, Minh T. wrote:
It still look odd as the value in s[2] is 2.0 which doesn’t seems to
have any rounding problem.In any case is there any workaround to fix get the condition as true ?
Floating point representations are in many cases (such as irrational
numbers like square root of 2) only approximations to a given value,
you therefore have to test that the value is accurate to a given
precision (number of significant digits). For example, given:x = (1.0 + 1.0) ** 0.5
you could write your test as:
(x ** 2.0).between?(1.9999, 2.0001)
Ellie
Eleanor McHugh
Games With Brains
http://slides.games-with-brains.netraise ArgumentError unless @reality.responds_to? :reason
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs