Hi
I wrote a simple test program, basically the program asks the user to
enter floats. the entered values shall be used as keys for Hash (the
values are irrelavent).
The program tries to find the lowest untaken key/float (floats are used
as keys).
please see attachment.
please run the prog, and enter the following:
0.01 - OK
0.02 - OK
0.03 - OK
0.04 - OK
0.05 - OK
0.06 - Problem
Can anyone explain to me what's going on here?
thanks
jason
Attachments:
http://www.ruby-forum.com/attachment/193/test.rb
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
jasonpurchase (2)
|
8/31/2007 1:38:19 AM |
|
Jason G. wrote:
> Hi
>
> I wrote a simple test program, basically the program asks the user to
> enter floats. the entered values shall be used as keys for Hash (the
> values are irrelavent).
>
> The program tries to find the lowest untaken key/float (floats are used
> as keys).
>
> please see attachment.
>
> please run the prog, and enter the following:
> 0.01 - OK
> 0.02 - OK
> 0.03 - OK
> 0.04 - OK
> 0.05 - OK
> 0.06 - Problem
>
> Can anyone explain to me what's going on here?
>
You should never compare floating point numbers for equality in any
language. This is true at least for C, C++, .NET, and Java, to name a
few. It just won't be accurate. Unlike integers, floats are not stored
as their true Platonic forms ;). If you really wanted to see how the
digits differed, you could print both numbers to a large number of
digits (printf("%.20f", my_number)). You don't even need to do any math
to see the roundoff error.
>> printf("%.50f", 1.1)
1.10000000000000008881784197001252323389053344726562
To compare floats, you must ask whether they are within a certain
threshold of each other.
Epsilon = 0.00000000001
return (num1-num2).abs < Epsilon # num1 == num2
Dan
|
|
0
|
|
|
|
Reply
|
dzwell (142)
|
8/31/2007 1:54:04 AM
|
|
thanks for the help
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
jasonpurchase (2)
|
8/31/2007 2:28:22 AM
|
|
Dan Zwell wrote:
> To compare floats, you must ask whether they are within a certain
> threshold of each other.
> Epsilon = 0.00000000001
> return (num1-num2).abs < Epsilon # num1 == num2
>
> Dan
>
>
Oops, I didn't realize that Ruby comes with an Epsilon. This should be a
fine test for equality:
return (num1-num2).abs < Float::EPSILON
Now, whether Float#==(other) should make this check might be worth
thinking about, but I really have no opinion on the matter--I'm used to
not comparing floats like this.
Dan
|
|
0
|
|
|
|
Reply
|
dzwell (142)
|
8/31/2007 2:41:34 AM
|
|
There is also a class called BigDecimal (or something like that) if
you want to have really accurate numbers and no floating-point errors.
On 8/30/07, Dan Zwell <dzwell@gmail.com> wrote:
> Dan Zwell wrote:
> > To compare floats, you must ask whether they are within a certain
> > threshold of each other.
> > Epsilon = 0.00000000001
> > return (num1-num2).abs < Epsilon # num1 == num2
> >
> > Dan
> >
> >
>
> Oops, I didn't realize that Ruby comes with an Epsilon. This should be a
> fine test for equality:
>
> return (num1-num2).abs < Float::EPSILON
>
> Now, whether Float#==(other) should make this check might be worth
> thinking about, but I really have no opinion on the matter--I'm used to
> not comparing floats like this.
>
> Dan
>
>
|
|
0
|
|
|
|
Reply
|
doug.meyer (7)
|
8/31/2007 2:50:49 AM
|
|
2007/8/31, doug meyer <doug.meyer@sigeps.org>:
> There is also a class called BigDecimal (or something like that) if
> you want to have really accurate numbers and no floating-point errors.
+1
|
|
0
|
|
|
|
Reply
|
ravwar (8)
|
8/31/2007 5:03:53 AM
|
|
Peña wrote:
--snip--
> irb(main):010:0> (0.05+0.01) - 0.06
> => 6.93889390390723e-18
>
> as mentioned by Dan, careful on comparing floats. And as to any
> precision subject, there is what we call significant digits..
>
> this floating problem is a faq and is very surprising on such a
> very high language such as ruby. can we address this? maybe create
> flag like $EPSILON=0 or something, or may flag to revert to rational
> or bigdeci like $FLOAT_PROCESSOR=RATIONAL...
>
Unfortunately, there is no easy solution to this problem. Here is a
catalog of often proposed solutions and why they do not work:
1 (proposed by doug meyer in this thread) Always use
(x-y).abs < Float::EPSILON
as a test for equality.
This won't work because the rounding error easily can get bigger than
Float::EPSILON, especially when dealing with numbers that are bigger
than unity. e.g.
y = 100.1 + 0.3
y - 100.4 # => -1.421e-14, while Float::EPSILON = 2.22e-16
2 Always use
(x-y).abs < (x.abs + y.abs) * Float::EPSILON)
as a test for equality.
Better than the first proposal, but won't work if the rounding error
gets too large after a complex computation.
In addition, (1) and (2) suffer from the problem that x==y and y==z do
not imply x==z.
3 Use Bigdezimal
This only shifts the problem a few decimal places down, and tests for
equality will fail as with the normal floats.
4 Use Rationals
Works if you only have to deal with rational operations. But doesn't
solve the following
x = sqrt(2)
y = x + 1
x + 0.2 == y - 0.8 # => false
In addition, rational arithmetic can produce huge numbers pretty fast,
and this will slow down computations enormously.
5 Use a symbolic math package
This could in theory solve the issue with equality, but in practice there
is no way to decide that two symbolic representations of a number are the
same, like
1 / (sqrt(2) - 1) == sqrt(2) + 1
Also, very, very slow.
6 Use interval arithmetic
Gives you strict bounds on your solution, but can't answer x==y.
Summing up, when using floating point arithmetic there is no one true way.
There is no substitute for understanding numbers and analyzing your problem.
HTH,
Michael
|
|
0
|
|
|
|
Reply
|
michael.ulm (77)
|
8/31/2007 6:25:17 AM
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Michael Ulm wrote:
> Unfortunately, there is no easy solution to this problem. Here is a
> catalog of often proposed solutions and why they do not work:
>
> 1 (proposed by doug meyer in this thread) Always use
> (x-y).abs < Float::EPSILON
> as a test for equality.
>
> This won't work because the rounding error easily can get bigger than
> Float::EPSILON, especially when dealing with numbers that are bigger
> than unity. e.g.
> y = 100.1 + 0.3
> y - 100.4 # => -1.421e-14, while Float::EPSILON = 2.22e-16
>
> 2 Always use (x-y).abs < (x.abs + y.abs) * Float::EPSILON) as a test
> for equality.
>
> Better than the first proposal, but won't work if the rounding error
> gets too large after a complex computation.
> In addition, (1) and (2) suffer from the problem that x==y and y==z do
> not imply x==z.
>
> 3 Use Bigdezimal
>
> This only shifts the problem a few decimal places down, and tests for
> equality will fail as with the normal floats.
>
> 4 Use Rationals
>
> Works if you only have to deal with rational operations. But doesn't
> solve the following
> x = sqrt(2)
> y = x + 1
> x + 0.2 == y - 0.8 # => false
> In addition, rational arithmetic can produce huge numbers pretty fast,
> and this will slow down computations enormously.
> 5 Use a symbolic math package
>
> This could in theory solve the issue with equality, but in practice there
> is no way to decide that two symbolic representations of a number are the
> same, like
> 1 / (sqrt(2) - 1) == sqrt(2) + 1
> Also, very, very slow.
>
> 6 Use interval arithmetic
>
> Gives you strict bounds on your solution, but can't answer x==y.
>
>
> Summing up, when using floating point arithmetic there is no one true way.
> There is no substitute for understanding numbers and analyzing your
> problem.
Well ... OK ... but ...
This whole floating-point thing comes up here on a weekly basis, and
I'll bet it comes up on all the other language mailing lists too. No
matter how many times you repeat this, no matter how many web sites
explaining floating point arithmetic you point people to, etc., you are
still going to get people who don't know how it works and have
expectations that aren't realistic. An awful lot of calculators have
been built using decimal arithmetic just because there are a few less
"anomalies" that need to be explained.
People like me who do number crunching for a living know all this stuff
inside and out. I actually learned the basics of scientific computing in
scaled fixed-point arithmetic, and it's only been in recent years (since
the Pentium, in fact) that just about every computer you're likely to
touch has had floating point hardware. Before that, you were likely to
be dealing with slow and inaccurate libraries emulating the hardware
unless you were in a scientific research environment. And it's also been
only a few more years since nearly all new architectures supported
(mostly) the IEEE floating point standard.
Before that, it was chaos -- most 32-bit floating point arithmetic was
unusable except for data storage, the reigning supercomputers had
floating point units optimized for speed at the expense of correctness,
you actually had to pay for good math libraries and whole books of
garbage number crunching algorithms were popular best-sellers. In short,
even the folks who knew very well how it *should* be done made both
necessary compromises and serious mistakes. It took some brave souls
like William Kahan several years to get some of the more obvious garbage
out of "common practice".
So give the newbies a break on this issue -- the professionals have only
been doing it mostly right since about 1990. :)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFG179D8fKMegVjSM8RAnaZAJ0X16UuHOEvWc5iZDurg7f607xr8QCfed+C
FG+18FnY10HxP+8t6R/62bM=
=jJ+X
-----END PGP SIGNATURE-----
|
|
0
|
|
|
|
Reply
|
znmeb (1667)
|
8/31/2007 7:12:07 AM
|
|
Michael Ulm wrote:
>> this floating problem is a faq and is very surprising on such a
>> very high language such as ruby. can we address this? maybe create
>> flag like $EPSILON=0 or something, or may flag to revert to rational
>> or bigdeci like $FLOAT_PROCESSOR=RATIONAL...
>
> Unfortunately, there is no easy solution to this problem. Here is a
> catalog of often proposed solutions and why they do not work:
>
> 2 Always use (x-y).abs < (x.abs + y.abs) * Float::EPSILON) as a test
> for equality.
>
> Better than the first proposal, but won't work if the rounding error
> gets too large after a complex computation.
> In addition, (1) and (2) suffer from the problem that x==y and y==z do
> not imply x==z.
But it would fix 99% of problems. It would be worth it just for the sake
of reducing those questions on the list :-P
Seriously though, since floating point calculations are approximative to
start with, what would be wrong with making them more intuitive
approximations? IMHO Float should use the above algorithm for == and
reserve normal floating point arithmetic for eql?
Daniel
|
|
0
|
|
|
|
Reply
|
dan-ml (239)
|
8/31/2007 8:03:38 AM
|
|
Daniel DeLorme wrote:
> Michael Ulm wrote:
>>> this floating problem is a faq and is very surprising on such a
>>> very high language such as ruby. can we address this? maybe create
>>> flag like $EPSILON=0 or something, or may flag to revert to rational
>>> or bigdeci like $FLOAT_PROCESSOR=RATIONAL...
>>
>> Unfortunately, there is no easy solution to this problem. Here is a
>> catalog of often proposed solutions and why they do not work:
>>
>> 2 Always use (x-y).abs < (x.abs + y.abs) * Float::EPSILON) as a test
>> for equality.
>>
>> Better than the first proposal, but won't work if the rounding error
>> gets too large after a complex computation.
>> In addition, (1) and (2) suffer from the problem that x==y and y==z do
>> not imply x==z.
>
> But it would fix 99% of problems. It would be worth it just for the sake
> of reducing those questions on the list :-P
>
> Seriously though, since floating point calculations are approximative to
> start with, what would be wrong with making them more intuitive
> approximations? IMHO Float should use the above algorithm for == and
> reserve normal floating point arithmetic for eql?
>
> Daniel
>
>
Michael wrote very convincingly that there is no simple solution that
will work in all cases. I'm convinced, at least. If there is no solution
that works 100% of the time, we can't give the illusion that there is.
To do so would be to teach bad programming practices to newcomers, and
that's not fair.
The current "==" in okay because it works the way a moderately
experienced programmer would expect. A perfect "==" that could deal with
floats would be even better, but we aren't gonna get that. A "==" that
seems like magic and almost always works is really pretty dangerous.
Dan
|
|
0
|
|
|
|
Reply
|
dzwell (142)
|
8/31/2007 8:18:31 AM
|
|
Hi,
Am Freitag, 31. Aug 2007, 17:03:38 +0900 schrieb Daniel DeLorme:
>> Unfortunately, there is no easy solution to this problem. Here is a
>> catalog of often proposed solutions and why they do not work:
>
> But it would fix 99% of problems. It would be worth it just for the sake of
> reducing those questions on the list :-P
>
> Seriously though, since floating point calculations are approximative to
> start with, what would be wrong with making them more intuitive
> approximations? IMHO Float should use the above algorithm for == and
> reserve normal floating point arithmetic for eql?
I alway liked it to be forced to decide what are countable
dimensions and what are continuous ones. This made my
programming style much clearer.
Bertram
--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de
|
|
0
|
|
|
|
Reply
|
lists2051 (431)
|
8/31/2007 8:19:52 AM
|
|
2007/8/31, Daniel DeLorme <dan-ml@dan42.com>:
> Michael Ulm wrote:
> >> this floating problem is a faq and is very surprising on such a
> >> very high language such as ruby. can we address this? maybe create
> >> flag like $EPSILON=0 or something, or may flag to revert to rational
> >> or bigdeci like $FLOAT_PROCESSOR=RATIONAL...
> >
> > Unfortunately, there is no easy solution to this problem. Here is a
> > catalog of often proposed solutions and why they do not work:
> >
> > 2 Always use (x-y).abs < (x.abs + y.abs) * Float::EPSILON) as a test
> > for equality.
> >
> > Better than the first proposal, but won't work if the rounding error
> > gets too large after a complex computation.
> > In addition, (1) and (2) suffer from the problem that x==y and y==z do
> > not imply x==z.
>
> But it would fix 99% of problems. It would be worth it just for the sake
> of reducing those questions on the list :-P
>
> Seriously though, since floating point calculations are approximative to
> start with, what would be wrong with making them more intuitive
> approximations? IMHO Float should use the above algorithm for == and
> reserve normal floating point arithmetic for eql?
And who decides about the size of epsilon and which algorithm to
choose? There is no one size fits all answer to that hence leaving
Float#== the way it is (i.e. compare for exact identical values) is
the only viable option. Otherwise you would soon see similar
questions on the list, i.e., "how come it sometimes works and
sometimes it doesn't". And they become more difficult to answer as
the cases are likely less easy to spot / explain.
Kind regards
robert
|
|
0
|
|
|
|
Reply
|
shortcutter (5766)
|
8/31/2007 9:41:14 AM
|
|
From: Robert Klemme [mailto:shortcutter@googlemail.com]=20
# And who decides about the size of epsilon and which algorithm to
# choose? There is no one size fits all answer to that hence leaving
# Float#=3D=3D the way it is (i.e. compare for exact identical values) =
is
# the only viable option. Otherwise you would soon see similar
# questions on the list, i.e., "how come it sometimes works and
# sometimes it doesn't". And they become more difficult to answer as
# the cases are likely less easy to spot / explain.
indeed :(
maybe i'm not "realistic" but i thought=20
0.05 + 0.01 =3D=3D 0.06 =3D> false
was "unrealistic" enough for a simple and plain 2 decimal arithmetic. =
Even people w zero-know on computers would laugh about it (yes, try =
explaining it to your wife or kids, eg).=20
For simple math (eg those dealing w money):
i can live w slowness in simple math (quite a paradox if you ask me).=20
i can live w 1/3 =3D=3D 0.3333333333 =3D>false
or that sqrt(2) =3D=3D 1.1414213562 =3D> false
i use bigdecimal. bigdecimal handles 0.05 + 0.01 =3D=3D 0.06 =3D> =
true
For complex math,
i can live w slowness (no question there).=20
bigdecimal easily handles sqrt(2) at 100 digits: 2.sqrt(100) =3D> =
#<BigDecimal:b7d74094,'0.1414213562 3730950488 0168872420 9698078569 =
6718753769 4807317667 9737990732 4784621070 3885038753 4327641572 =
7350138462 309122925E1',124(124)
so yes, i still use bigdecimal for complex math.
so regardless, of whether its simple or complex (or "highly precise" or =
not), i use bigdecimal. counting ang looping otoh has no problem w me =
since fixnum/bignum handles this flawlessly. (Also, note that big RDBMS =
like oracle and postgresql use BCD and fixed pt math for numerics).=20
So, my question probably is (maybe this could be addressed to Matz): How =
can i make ruby use a particular arithmetic, like bigdecimal eg, so that =
literals like 1.05, and operations like 1+1.01 are now handled as =
bigdecimals.
thank you and kind regards -botp
|
|
0
|
|
|
|
Reply
|
botp (987)
|
8/31/2007 9:55:41 AM
|
|
On 8/31/07, Pe=F1a, Botp <botp@delmonte-phil.com> wrote:
> From: Robert Klemme [mailto:shortcutter@googlemail.com]
> # And who decides about the size of epsilon and which algorithm to
> # choose? There is no one size fits all answer to that hence leaving
> # Float#=3D=3D the way it is (i.e. compare for exact identical values) is
> # the only viable option. Otherwise you would soon see similar
> # questions on the list, i.e., "how come it sometimes works and
> # sometimes it doesn't". And they become more difficult to answer as
> # the cases are likely less easy to spot / explain.
>
> indeed :(
>
> maybe i'm not "realistic" but i thought
>
> 0.05 + 0.01 =3D=3D 0.06 =3D> false
>
> was "unrealistic" enough for a simple and plain 2 decimal arithmetic. Eve=
n people w zero-know on computers would laugh about it (yes, try explaining=
it to your wife or kids, eg).
This seems indeed a very valid argument at first sight.
But I feel that it is not the case.
Ruby has Integers and Floats, it does not have Fixed Digit Decimals
that is all which is to discuss here, as long as we discuss Floats
Michael is just dead right, now saying that we should have something
which delivers
0.05 + 0.01 =3D=3D 0.06 =3D> true
is a slightly different issue.
Personally I do not miss it because if I want decimals to be precise
to n digits I will just multiply by 10**n, at least the precision is
clear than.
But that is a matter of taste, I guess.
Cheers
Robert
>
> For simple math (eg those dealing w money):
> i can live w slowness in simple math (quite a paradox if you ask me).
> i can live w 1/3 =3D=3D 0.3333333333 =3D>false
> or that sqrt(2) =3D=3D 1.1414213562 =3D> false
> i use bigdecimal. bigdecimal handles 0.05 + 0.01 =3D=3D 0.06 =3D> true
>
> For complex math,
> i can live w slowness (no question there).
> bigdecimal easily handles sqrt(2) at 100 digits: 2.sqrt(100) =3D> #<B=
igDecimal:b7d74094,'0.1414213562 3730950488 0168872420 9698078569 671875376=
9 4807317667 9737990732 4784621070 3885038753 4327641572 7350138462 3091229=
25E1',124(124)
> so yes, i still use bigdecimal for complex math.
>
> so regardless, of whether its simple or complex (or "highly precise" or n=
ot), i use bigdecimal. counting ang looping otoh has no problem w me since =
fixnum/bignum handles this flawlessly. (Also, note that big RDBMS like orac=
le and postgresql use BCD and fixed pt math for numerics).
>
> So, my question probably is (maybe this could be addressed to Matz): How =
can i make ruby use a particular arithmetic, like bigdecimal eg, so that li=
terals like 1.05, and operations like 1+1.01 are now handled as bigdecimals=
|
|
0
|
|
|
|
Reply
|
robert.dober (2193)
|
8/31/2007 10:34:58 AM
|
|
2007/8/31, Pe=F1a, Botp <botp@delmonte-phil.com>:
> From: Robert Klemme [mailto:shortcutter@googlemail.com]
> # And who decides about the size of epsilon and which algorithm to
> # choose? There is no one size fits all answer to that hence leaving
> # Float#=3D=3D the way it is (i.e. compare for exact identical values) is
> # the only viable option. Otherwise you would soon see similar
> # questions on the list, i.e., "how come it sometimes works and
> # sometimes it doesn't". And they become more difficult to answer as
> # the cases are likely less easy to spot / explain.
>
> indeed :(
>
> maybe i'm not "realistic" but i thought
>
> 0.05 + 0.01 =3D=3D 0.06 =3D> false
>
> was "unrealistic" enough for a simple and plain 2 decimal arithmetic. Eve=
n people w zero-know on computers would laugh about it (yes, try explaining=
it to your wife or kids, eg).
That's probably the exact reason why not your wife or kids write
software but people who are (hopefully) experts. :-) If you study
computer sciences you'll typically hit the topic of numeric issues at
some point.
> For simple math (eg those dealing w money):
> i can live w slowness in simple math (quite a paradox if you ask me).
> i can live w 1/3 =3D=3D 0.3333333333 =3D>false
> or that sqrt(2) =3D=3D 1.1414213562 =3D> false
> i use bigdecimal. bigdecimal handles 0.05 + 0.01 =3D=3D 0.06 =3D> true
>
> For complex math,
> i can live w slowness (no question there).
> bigdecimal easily handles sqrt(2) at 100 digits: 2.sqrt(100) =3D> #<B=
igDecimal:b7d74094,'0.1414213562 3730950488 0168872420 9698078569 671875376=
9 4807317667 9737990732 4784621070 3885038753 4327641572 7350138462 3091229=
25E1',124(124)
> so yes, i still use bigdecimal for complex math.
>
> so regardless, of whether its simple or complex (or "highly precise" or n=
ot), i use bigdecimal. counting ang looping otoh has no problem w me since =
fixnum/bignum handles this flawlessly. (Also, note that big RDBMS like orac=
le and postgresql use BCD and fixed pt math for numerics).
>
> So, my question probably is (maybe this could be addressed to Matz): How =
can i make ruby use a particular arithmetic, like bigdecimal eg, so that li=
terals like 1.05, and operations like 1+1.01 are now handled as bigdecimals=
|
|
0
|
|
|
|
Reply
|
shortcutter (5766)
|
8/31/2007 12:02:25 PM
|
|
Hi,
Try converting to strings e.g:
irb(main):004:0> (0.05 + 0.01).to_s =3D=3D 0.06.to_s
=3D> true
BR
Davor
On 31 Aug, 14:02, "Robert Klemme" <shortcut...@googlemail.com> wrote:
> 2007/8/31, Pe=F1a, Botp <b...@delmonte-phil.com>:
>
>
>
>
>
> > From: Robert Klemme [mailto:shortcut...@googlemail.com]
> > # And who decides about the size of epsilon and which algorithm to
> > # choose? There is no one size fits all answer to that hence leaving
> > # Float#=3D=3D the way it is (i.e. compare for exact identical values) =
is
> > # the only viable option. Otherwise you would soon see similar
> > # questions on the list, i.e., "how come it sometimes works and
> > # sometimes it doesn't". And they become more difficult to answer as
> > # the cases are likely less easy to spot / explain.
>
> > indeed :(
>
> > maybe i'm not "realistic" but i thought
>
> > 0.05 + 0.01 =3D=3D 0.06 =3D> false
>
> > was "unrealistic" enough for a simple and plain 2 decimal arithmetic. E=
ven people w zero-know on computers would laugh about it (yes, try explaini=
ng it to your wife or kids, eg).
>
> That's probably the exact reason why not your wife or kids write
> software but people who are (hopefully) experts. :-) If you study
> computer sciences you'll typically hit the topic of numeric issues at
> some point.
>
> > For simple math (eg those dealing w money):
> > i can live w slowness in simple math (quite a paradox if you ask me).
> > i can live w 1/3 =3D=3D 0.3333333333 =3D>false
> > or that sqrt(2) =3D=3D 1.1414213562 =3D> false
> > i use bigdecimal. bigdecimal handles 0.05 + 0.01 =3D=3D 0.06 =3D> tr=
ue
>
> > For complex math,
> > i can live w slowness (no question there).
> > bigdecimal easily handles sqrt(2) at 100 digits: 2.sqrt(100) =3D> #=
<BigDecimal:b7d74094,'0.1414213562 3730950488 0168872420 9698078569 6718753=
769 4807317667 9737990732 4784621070 3885038753 4327641572 7350138462 30912=
2925E1',124(124)
> > so yes, i still use bigdecimal for complex math.
>
> > so regardless, of whether its simple or complex (or "highly precise" or=
not), i use bigdecimal. counting ang looping otoh has no problem w me sinc=
e fixnum/bignum handles this flawlessly. (Also, note that big RDBMS like or=
acle and postgresql use BCD and fixed pt math for numerics).
>
> > So, my question probably is (maybe this could be addressed to Matz): Ho=
w can i make ruby use a particular arithmetic, like bigdecimal eg, so that =
literals like 1.05, and operations like 1+1.01 are now handled as bigdecima=
ls.
>
> Well, you could provide your formula as strings and convert it to
> something that creates BigDecimals along the way, like
>
> irb(main):015:0> "0.01+0.05".gsub(%r{\d+(?:\.\d*)?}, "BigDecimal.new('\\&=
')")
> =3D> "BigDecimal.new('0.01')+BigDecimal.new('0.05')"
> irb(main):016:0> eval("0.01+0.05".gsub(%r{\d+(?:\.\d*)?},
> "BigDecimal.new('\\&')"))
> =3D> #<BigDecimal:7ff6dd60,'0.6E-1',4(12)>
>
> # note this is of course not a proper solution since the RX does not
> match all valid floats
>
> Kind regards
>
> robert- D=F6lj citerad text -
>
> - Visa citerad text -
|
|
0
|
|
|
|
Reply
|
davor (1)
|
8/31/2007 2:07:41 PM
|
|
On 8/30/07, doug meyer <doug.meyer@sigeps.org> wrote:
> There is also a class called BigDecimal (or something like that) if
> you want to have really accurate numbers and no floating-point errors.
A warning on things like BigDecimal.
Unless I'm mistaken it's still stored in twos compliment, which means
you'll still end up with the same sort of floating point problems
(albeit further down), and the same numbers that you can't express
exactly with a normal float, can't be expressed exactly with a
BigDecimal.
You'd think some fixed point math libraries would help, but be
careful, because many of those _also_ store in twos compliment.
--Kyle
|
|
0
|
|
|
|
Reply
|
kyleaschmitt (377)
|
8/31/2007 2:18:25 PM
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Bertram Scharpf wrote:
> Hi,
>
> Am Freitag, 31. Aug 2007, 17:03:38 +0900 schrieb Daniel DeLorme:
>>> Unfortunately, there is no easy solution to this problem. Here is a
>>> catalog of often proposed solutions and why they do not work:
>> But it would fix 99% of problems. It would be worth it just for the sake of
>> reducing those questions on the list :-P
>>
>> Seriously though, since floating point calculations are approximative to
>> start with, what would be wrong with making them more intuitive
>> approximations? IMHO Float should use the above algorithm for == and
>> reserve normal floating point arithmetic for eql?
>
> I alway liked it to be forced to decide what are countable
> dimensions and what are continuous ones. This made my
> programming style much clearer.
>
> Bertram
>
>
Well ... since *everything* in computing is countable ... :)
But seriously, real computing on real digital machines involves
translation from infinite and/or continuous semantics to very large
finite discrete processes. About the only thing that's truly infinite is
the time it takes to complete
while true do
end
But there are some techniques not terribly well known that improve on
floating point arithmetic as normally implemented in hardware. They're
too expensive for mass-market hardware, so they're usually implemented
in software. Interval arithmetic has already been mentioned, but there
are some others. Try "A New Approach to Scientific Computation" by
Kulisch and Miranker.
Most of these are historical curiosities these days because of the
widespread distribution of high-performance open-source libraries for
exact and symbolic computation, such as GiNaC, GMP, CLN, etc. And it's
pretty easy using SWIG to interface one or more of these to Ruby.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFG2DJg8fKMegVjSM8RAqz5AJ9iT+1hEDwtuYht2pnp/cnup/B2QwCgzIte
BwjwjradiTPNAV4h8LX/bj8=
=wT6P
-----END PGP SIGNATURE-----
|
|
0
|
|
|
|
Reply
|
znmeb (1667)
|
8/31/2007 3:23:17 PM
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Kyle Schmitt wrote:
> On 8/30/07, doug meyer <doug.meyer@sigeps.org> wrote:
>> There is also a class called BigDecimal (or something like that) if
>> you want to have really accurate numbers and no floating-point errors.
>
> A warning on things like BigDecimal.
> Unless I'm mistaken it's still stored in twos compliment, which means
> you'll still end up with the same sort of floating point problems
> (albeit further down), and the same numbers that you can't express
> exactly with a normal float, can't be expressed exactly with a
> BigDecimal.
>
> You'd think some fixed point math libraries would help, but be
> careful, because many of those _also_ store in twos compliment.
>
> --Kyle
>
>
IIRC BigDecimal is in fact stored in (pregnant pause) Binary Coded
Decimal. But I should check that.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFG2DKp8fKMegVjSM8RAsTQAKCNicl4roW3uh7LWLERNMxbtL0dnQCdHTAY
/Y2wWjyVegtTECn6Ur32v30=
=hAqx
-----END PGP SIGNATURE-----
|
|
0
|
|
|
|
Reply
|
znmeb (1667)
|
8/31/2007 3:24:39 PM
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Robert Klemme wrote:
> 2007/8/31, Pe�a, Botp <botp@delmonte-phil.com>:
>> From: Robert Klemme [mailto:shortcutter@googlemail.com]
>> # And who decides about the size of epsilon and which algorithm to
>> # choose? There is no one size fits all answer to that hence leaving
>> # Float#== the way it is (i.e. compare for exact identical values) is
>> # the only viable option. Otherwise you would soon see similar
>> # questions on the list, i.e., "how come it sometimes works and
>> # sometimes it doesn't". And they become more difficult to answer as
>> # the cases are likely less easy to spot / explain.
>>
>> indeed :(
>>
>> maybe i'm not "realistic" but i thought
>>
>> 0.05 + 0.01 == 0.06 => false
>>
>> was "unrealistic" enough for a simple and plain 2 decimal arithmetic. Even people w zero-know on computers would laugh about it (yes, try explaining it to your wife or kids, eg).
>
> That's probably the exact reason why not your wife or kids write
> software but people who are (hopefully) experts. :-) If you study
> computer sciences you'll typically hit the topic of numeric issues at
> some point.
Actually, unless you're a (hard) science or engineering major, you
probably won't. Numerical analysis/methods aren't really considered part
of "computer science". Computer science is mostly about *discrete*
mathematics, data structures, programming languages and their
interpreters and compilers, etc. And you probably won't get it in a
"software engineering" program either. Applied mathematics is your best
shot, I think.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFG2DP18fKMegVjSM8RAhnIAKDO4mMSDAh/pJ1BSe4ICFj4tD+9vACfdgh5
CZvGLjrSlH4QVf6sEG2b4Lc=
=XRUf
-----END PGP SIGNATURE-----
|
|
0
|
|
|
|
Reply
|
znmeb (1667)
|
8/31/2007 3:30:08 PM
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Dan Zwell wrote:
> Michael wrote very convincingly that there is no simple solution that
> will work in all cases. I'm convinced, at least. If there is no solution
> that works 100% of the time, we can't give the illusion that there is.
> To do so would be to teach bad programming practices to newcomers, and
> that's not fair.
>
> The current "==" in okay because it works the way a moderately
> experienced programmer would expect. A perfect "==" that could deal with
> floats would be even better, but we aren't gonna get that. A "==" that
> seems like magic and almost always works is really pretty dangerous.
>
> Dan
>
>
Yeah ... even people like me who have spent several decades in this
branch of computing need to be reminded of these things occasionally.
What *I* wish Ruby had for scientific number-crunching is built-in
floating point arrays, rather than having to pass potential large
objects into and out of C language libraries to get number crunching done.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFG2DTf8fKMegVjSM8RAudJAJ9wOyvmdtgSRgVVUpbXem6nLUpfKQCdEspD
YgYD17sas15mJA/Q1kGMwJQ=
=kZx0
-----END PGP SIGNATURE-----
|
|
0
|
|
|
|
Reply
|
znmeb (1667)
|
8/31/2007 3:33:53 PM
|
|
On Sat, 01 Sep 2007 00:24:39 +0900, M. Edward (Ed) Borasky wrote:
> Kyle Schmitt wrote:
>> On 8/30/07, doug meyer <doug.meyer@sigeps.org> wrote:
>>> There is also a class called BigDecimal (or something like that) if
>>> you want to have really accurate numbers and no floating-point errors.
>>
>> A warning on things like BigDecimal.
>> Unless I'm mistaken it's still stored in twos compliment, which means
>> you'll still end up with the same sort of floating point problems
>> (albeit further down), and the same numbers that you can't express
>> exactly with a normal float, can't be expressed exactly with a
>> BigDecimal.
>>
>> You'd think some fixed point math libraries would help, but be careful,
>> because many of those _also_ store in twos compliment.
>>
>> --Kyle
>>
>>
> IIRC BigDecimal is in fact stored in (pregnant pause) Binary Coded
> Decimal. But I should check that.
Neither one can represent 1/3 or sqrt(2) exactly.
--
Ken Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu/~kbloom1/
|
|
0
|
|
|
|
Reply
|
kbloom (554)
|
8/31/2007 4:01:59 PM
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Ken Bloom wrote:
> On Sat, 01 Sep 2007 00:24:39 +0900, M. Edward (Ed) Borasky wrote:
>> Kyle Schmitt wrote:
>>> On 8/30/07, doug meyer <doug.meyer@sigeps.org> wrote:
>>>> There is also a class called BigDecimal (or something like that) if
>>>> you want to have really accurate numbers and no floating-point errors.
>>> A warning on things like BigDecimal.
>>> Unless I'm mistaken it's still stored in twos compliment, which means
>>> you'll still end up with the same sort of floating point problems
>>> (albeit further down), and the same numbers that you can't express
>>> exactly with a normal float, can't be expressed exactly with a
>>> BigDecimal.
>>>
>>> You'd think some fixed point math libraries would help, but be careful,
>>> because many of those _also_ store in twos compliment.
>>>
>>> --Kyle
>>>
>>>
>> IIRC BigDecimal is in fact stored in (pregnant pause) Binary Coded
>> Decimal. But I should check that.
>
> Neither one can represent 1/3 or sqrt(2) exactly.
>
Which is why there are libraries and packages like GiNaC, CLN, GMP,
Singular, Maxima, Axiom, ...
I personally think Ruby's libraries for exact arithmetic are better than
those in the other scripting languages -- I don't think anyone else has
BigDecimal, Rational, Complex, Matrix, "mathn" and Bignums built in or
part of the *standard* libraries. The only thing that's missing, as I
noted earlier, is the ability to declare a physically contiguous block
of RAM as a vector of floating point or complex numbers and operate on
them as such. For that, you need to go to an external package like NArray.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD4DBQFG2Ept8fKMegVjSM8RAiqFAJi/iWlXdhu/4UNm8y3WV+g6tlaCAKC5PDDS
yWzL3Cnk6zkYnMcA/Rl4dw==
=bW0a
-----END PGP SIGNATURE-----
|
|
0
|
|
|
|
Reply
|
znmeb (1667)
|
8/31/2007 5:06:07 PM
|
|
On 31.08.2007 17:30, M. Edward (Ed) Borasky wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>=20
> Robert Klemme wrote:
>> 2007/8/31, Pe=F1a, Botp <botp@delmonte-phil.com>:
>>> From: Robert Klemme [mailto:shortcutter@googlemail.com]
>>> # And who decides about the size of epsilon and which algorithm to
>>> # choose? There is no one size fits all answer to that hence leaving=
>>> # Float#=3D=3D the way it is (i.e. compare for exact identical values=
) is
>>> # the only viable option. Otherwise you would soon see similar
>>> # questions on the list, i.e., "how come it sometimes works and
>>> # sometimes it doesn't". And they become more difficult to answer as=
>>> # the cases are likely less easy to spot / explain.
>>>
>>> indeed :(
>>>
>>> maybe i'm not "realistic" but i thought
>>>
>>> 0.05 + 0.01 =3D=3D 0.06 =3D> false
>>>
>>> was "unrealistic" enough for a simple and plain 2 decimal arithmetic.=
Even people w zero-know on computers would laugh about it (yes, try expl=
aining it to your wife or kids, eg).
>> That's probably the exact reason why not your wife or kids write
>> software but people who are (hopefully) experts. :-) If you study
>> computer sciences you'll typically hit the topic of numeric issues at
>> some point.
>=20
> Actually, unless you're a (hard) science or engineering major, you
> probably won't. Numerical analysis/methods aren't really considered par=
t
> of "computer science". Computer science is mostly about *discrete*
> mathematics, data structures, programming languages and their
> interpreters and compilers, etc. And you probably won't get it in a
> "software engineering" program either. Applied mathematics is your best=
> shot, I think.
Of course I can speak only for Germany but I had a mandatory lecture on=20
numerical analysis during my CS studies. IIRC it was even during the=20
lower grade phase (dunno the proper English wording), i.e. within the=20
first two years. But then again, the "Diplom" is probably considered=20
roughly equivalent to a major. Somehow I thought numerical effects were =
so basic and common that they are mentioned in all other places as well. =
Thanks for pointing this out.
Kind regards
robert
|
|
0
|
|
|
|
Reply
|
shortcutter (5766)
|
8/31/2007 9:45:10 PM
|
|
On Aug 31, 1:25 am, Michael Ulm <michael....@isis-papyrus.com> wrote:
> 2 Always use
> (x-y).abs < (x.abs + y.abs) * Float::EPSILON)
> as a test for equality.
>
> Better than the first proposal, but won't work if the rounding error
> gets too large after a complex computation.
> In addition, (1) and (2) suffer from the problem that x==y and y==z do
> not imply x==z.
How about
(a - b).abs / [a, b].map{|x| a.abs}.min < Float::EPSILON
?
def eq( a, b )
(a - b).abs / [a, b].map{|x| a.abs}.min < Float::EPSILON
end
DATA.each{|s|
strings = s.chomp.split(";")
floats = strings.map{|s| eval(s) }
puts strings.join( " == " ) +
" : #{floats[0]==floats[1]} #{ eq( *floats ) }"
}
__END__
(0.05+0.01);0.06
(0.34+0.01);0.35
9.123456789;9.1234567891
9.123456789012345;9.1234567890123451
9.12345678901234e-9;9.123456789012341e-9
=== output ===
(0.05+0.01) == 0.06 : false true
(0.34+0.01) == 0.35 : false true
9.123456789 == 9.1234567891 : false false
9.123456789012345 == 9.1234567890123451 : false true
9.12345678901234e-9 == 9.123456789012341e-9 : false true
|
|
0
|
|
|
|
Reply
|
w_a_x_man (2778)
|
8/31/2007 10:01:56 PM
|
|
On 8/31/07, Kyle Schmitt <kyleaschmitt@gmail.com> wrote:
> On 8/30/07, doug meyer <doug.meyer@sigeps.org> wrote:
> > There is also a class called BigDecimal (or something like that) if
> > you want to have really accurate numbers and no floating-point errors.
>
> A warning on things like BigDecimal.
> Unless I'm mistaken it's still stored in twos compliment, which means
> you'll still end up with the same sort of floating point problems
> (albeit further down), and the same numbers that you can't express
> exactly with a normal float, can't be expressed exactly with a
> BigDecimal.
>
Um, 2's compliment is not a cause of floating point error. IEEE
floating point numbers do not use two's complement, they have a sign
bit. Two's complement is just a way of encoding the sign of a value.
> You'd think some fixed point math libraries would help, but be
> careful, because many of those _also_ store in twos compliment.
>
Again, the use of two's complement or lack thereof is totally irrelevant.
> --Kyle
>
>
|
|
0
|
|
|
|
Reply
|
logancapaldo (886)
|
8/31/2007 11:16:42 PM
|
|
I am in the Sophomore year of a CS degree at Washing State University
and I am currently enrolled in a mandatory Numerical Computing class.
While it is very much more CS-than-math it does, of course, cover
topics like FP implementations and related issues.
|
|
0
|
|
|
|
Reply
|
pstickne (43)
|
8/31/2007 11:55:42 PM
|
|
From: Robert Klemme [mailto:shortcutter@googlemail.com]=20
# Well, you could provide your formula as strings and convert it to
# something that creates BigDecimals along the way, like
# irb(main):015:0> "0.01+0.05".gsub(%r{\d+(?:\.\d*)?},=20
# "BigDecimal.new('\\&')")
# =3D> "BigDecimal.new('0.01')+BigDecimal.new('0.05')"
# irb(main):016:0> eval("0.01+0.05".gsub(%r{\d+(?:\.\d*)?},
# "BigDecimal.new('\\&')"))
# =3D> #<BigDecimal:7ff6dd60,'0.6E-1',4(12)>
# note this is of course not a proper solution since the RX does not
# match all valid floats
:)
on my case, i just want ruby to default to bigdeci (or whatever i want) =
instead of float. meaning, i choose any math processor i want. is that =
possible now, or in near future of ruby?
kind regards -botp
|
|
0
|
|
|
|
Reply
|
botp (987)
|
9/1/2007 2:42:03 AM
|
|
On 8/31/07, Logan Capaldo <logancapaldo@gmail.com> wrote:
> On 8/31/07, Kyle Schmitt <kyleaschmitt@gmail.com> wrote:
> > On 8/30/07, doug meyer <doug.meyer@sigeps.org> wrote:
> > > There is also a class called BigDecimal (or something like that) if
> > > you want to have really accurate numbers and no floating-point errors.
> >
> > A warning on things like BigDecimal.
> > Unless I'm mistaken it's still stored in twos compliment, which means
> > you'll still end up with the same sort of floating point problems
> > (albeit further down), and the same numbers that you can't express
> > exactly with a normal float, can't be expressed exactly with a
> > BigDecimal.
> >
> Um, 2's compliment is not a cause of floating point error. IEEE
> floating point numbers do not use two's complement, they have a sign
> bit. Two's complement is just a way of encoding the sign of a value.
Used the wrong term :P sue me. I guess that's why I should lookup
stuff before responding ;)
Anyway it's all based on the fact that you can't store some numbers
exactly as sum of different xes for 2**(-x).
--Kyle
|
|
0
|
|
|
|
Reply
|
kyleaschmitt (377)
|
9/1/2007 8:33:17 PM
|
|
On 01.09.2007 22:33, Kyle Schmitt wrote:
> On 8/31/07, Logan Capaldo <logancapaldo@gmail.com> wrote:
>> On 8/31/07, Kyle Schmitt <kyleaschmitt@gmail.com> wrote:
>>> On 8/30/07, doug meyer <doug.meyer@sigeps.org> wrote:
>>>> There is also a class called BigDecimal (or something like that) if
>>>> you want to have really accurate numbers and no floating-point errors.
>>> A warning on things like BigDecimal.
>>> Unless I'm mistaken it's still stored in twos compliment, which means
>>> you'll still end up with the same sort of floating point problems
>>> (albeit further down), and the same numbers that you can't express
>>> exactly with a normal float, can't be expressed exactly with a
>>> BigDecimal.
>>>
>> Um, 2's compliment is not a cause of floating point error. IEEE
>> floating point numbers do not use two's complement, they have a sign
>> bit. Two's complement is just a way of encoding the sign of a value.
>
> Used the wrong term :P sue me. I guess that's why I should lookup
> stuff before responding ;)
> Anyway it's all based on the fact that you can't store some numbers
> exactly as sum of different xes for 2**(-x).
BigDecimals do *not* use binary representation. That's why they are
called Big/Decimal/.
If you want to give a warning then it should be that for *any*
representation (binary, decimal, hex, octal whatever) there are
fractional numbers that cannot be represented properly with that
representation. You have to be aware of this for *all* representation
types. The reason people are surprised is typically because we enter
float numbers in decimal but systems use binary representation (which is
standardized btw.) internally and that has other numbers that it cannot
properly represent. BigDecimal helps because it uses the same
representation internally that we are used to use for numbers - decimal
digits.
Kind regards
robert
|
|
0
|
|
|
|
Reply
|
shortcutter (5766)
|
9/2/2007 12:09:10 PM
|
|
On 31.08.2007 16:07, Davor wrote:
> Hi,
> Try converting to strings e.g:
> irb(main):004:0> (0.05 + 0.01).to_s == 0.06.to_s
> => true
I think what puzzles is while 0.05+0.01 == 0.06 returns false, the
strings _do_ match.
def float_check(a,b)
p [a==b,a.to_s == b.to_s]
end
float_check(0.06,0.06) # -> [true,true]
float_check(0.05+0.01,0.06) # -> [false,true]
Most other programming languages either have no format-less .to_s
function (like in C) or return values at inspection time so that
people get aware of the issue more easily. In Python it is obvious
that 0.05+0.01 == 0.06 is false.
$ python
>>> 0.05
0.050000000000000003
>>> 0.01
0.01
>>> 0.05+0.01
0.060000000000000005
>>> 0.06
0.059999999999999998
I don't understand why Ruby 'rounds' values with .inspect (and
to_s) opposed to Marshal.dump. Compare its output with the one
Python gives (this code is for Ruby 1.8.6):
[0.05,0.01,0.05+0.01,0.06].each do |v|
p Marshal.dump(v).sub(/....([^\000]*).*/,'\1')
end
Output:
"0.050000000000000003"
"0.01"
"0.060000000000000005"
"0.059999999999999998"
Did I miss something here, is there a way to make Float#to_s (and,
thus, Float#inspect) give the same output as Marshal?
- Matthias
|
|
0
|
|
|
|
Reply
|
matthias8993 (38)
|
9/3/2007 10:09:18 AM
|
|
Matthias Wächter wrote:
> I don't understand why Ruby 'rounds' values with .inspect (and
> .to_s) opposed to Marshal.dump. Compare its output with the one
> Python gives (this code is for Ruby 1.8.6):
Because for an *inspection* a precision of 5, 6 places are sufficient.
Inspect isn't used for printing values other than debugging etc.
In the opposite, having 40+ places for every float in your debug output
would be rather annoying and almost always of little help.
If python choses to be annoying, be it so, I'm happy ruby doesn't.
Use sprintf/String#% if you want to specify the precision you want your
output.
Marshal.dump on the other hand is serializing, of course you don't want
your floats truncated just because you're serializing.
As for having a way: you can always open the Float class and define
to_s to your liking. Same for inspect.
Regards
Stefan
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
apeiros (266)
|
9/3/2007 10:57:11 AM
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Stefan Rusterholz wrote:
> Marshal.dump on the other hand is serializing, of course you don't want
> your floats truncated just because you're serializing.
Excuse me -- does Marshal.dump serialize floats in text or in binary?
I'd hope it was binary. A *YAML* serializer would have to do it in text,
although they could obviously encode binary in base 64 or hex.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFG3FVV8fKMegVjSM8RAlq1AKCCJbOHo7WXyZQUSwt2IWHb0rRiCwCfbYpU
JabnGpU8CXJgl/J1oeEgruE=
=GUe1
-----END PGP SIGNATURE-----
|
|
0
|
|
|
|
Reply
|
znmeb (1667)
|
9/3/2007 6:41:47 PM
|
|
M. Edward (Ed) Borasky wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Stefan Rusterholz wrote:
>
>> Marshal.dump on the other hand is serializing, of course you don't want
>> your floats truncated just because you're serializing.
> Excuse me -- does Marshal.dump serialize floats in text or in binary?
> I'd hope it was binary. A *YAML* serializer would have to do it in text,
> although they could obviously encode binary in base 64 or hex.
The number itself is in acsii:
irb(main):006:0> x = 1.234e120
=> 1.234e+120
irb(main):007:0> Marshal.dump(x)
=> "\004\bf\0371.2340000000000001e+120\000@`"
Maybe this is for compatibility, in case ruby is running on some oddball
system without the standard float formats?
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
|
|
0
|
|
|
|
Reply
|
vjoel (2600)
|
9/3/2007 7:00:32 PM
|
|
On Aug 31, 12:25 am, Michael Ulm <michael....@isis-papyrus.com> wrote:
<snip>
> Unfortunately, there is no easy solution to this problem.
<snip>
Here's my naive, DWIM approach:
class Float
def ==(other)
self.to_s == other.to_s
end
end
Regards,
Dan
|
|
0
|
|
|
|
Reply
|
djberg96 (1011)
|
9/3/2007 11:07:28 PM
|
|
Daniel Berger wrote:
>
> On Aug 31, 12:25 am, Michael Ulm <michael....@isis-papyrus.com> wrote:
>
> <snip>
>
>> Unfortunately, there is no easy solution to this problem.
>
> <snip>
>
> Here's my naive, DWIM approach:
>
> class Float
> def ==(other)
> self.to_s == other.to_s
> end
> end
>
Oh yes, nice one. This fulfills
'from x==y and y==z follows x==z'
Unfortunately it does not fulfill some other properties one
wants to have; e.g. it violates
'from x==y follows x+z==y+z'
for example
> x, y = 1.0/3.0, 0.333333333333333
> x.to_s == y.to_s # => true
> (x+x).to_s == (y+x).to_s # => false
In particular, you don't have
'from x==y follows x-y==0'
for example
> x, y = 0.6, 6 * 0.1
> x.to_s == y.to_s # => true
> (x - y).to_s == 0.to_s # => false
HTH,
Michael
|
|
0
|
|
|
|
Reply
|
michael.ulm (77)
|
9/4/2007 6:56:12 AM
|
|
From: Michael Ulm [mailto:michael.ulm@isis-papyrus.com]=20
# Daniel Berger wrote:
# > class Float
# > def =3D=3D(other)
# > self.to_s =3D=3D other.to_s
# > end
# > end
# Oh yes, nice one. This fulfills=20
# 'from x=3D=3Dy and y=3D=3Dz follows x=3D=3Dz'
# Unfortunately it does not fulfill some other properties one
w a little help fr bigdecimal, a little goes a long long way
> class Float
> def to_dec
> BigDecimal.new(self.to_s)
> end
> end
=3D> nil
> class Fixnum
> def to_dec
> BigDecimal.new(self.to_s)
> end
> end
=3D> nil
> x=3D0.06.to_dec
> y=3D0.05.to_dec + 0.01.to_dec
> x=3D=3Dy
=3D> true
> z=3D0.02.to_dec+0.04.to_dec
> y=3D=3Dz
=3D> true
> z=3D=3Dy
=3D> true
> x=3D=3Dz
=3D> true
> z=3D=3Dx
=3D> true
# wants to have; e.g. it violates
# 'from x=3D=3Dy follows x+z=3D=3Dy+z'
> x+z =3D=3D y+z
=3D> true
> (x+z).to_s =3D=3D (y+z).to_s
=3D> true
> puts (x+z)
0.12E0
=3D> nil
# for example
# In particular, you don't have
#=20
# 'from x=3D=3Dy follows x-y=3D=3D0'
> x=3D=3Dy
=3D> true
> x-y =3D=3D 0
=3D> true
=20
# for example
#=20
# > x, y =3D 0.6, 6 * 0.1
# > x.to_s =3D=3D y.to_s # =3D> true
# > (x - y).to_s =3D=3D 0.to_s # =3D> false
> x, y =3D 0.6.to_dec, 6 * 0.1.to_dec
> (x - y) =3D=3D 0
=3D> true
> (x - y) =3D=3D 0.to_dec
=3D> true
> (x - y).to_s =3D=3D 0.to_dec.to_s
=3D> true
kind regards -botp
|
|
0
|
|
|
|
Reply
|
botp (987)
|
9/4/2007 7:29:34 AM
|
|
Pe�a wrote:
> From: Michael Ulm [mailto:michael.ulm@isis-papyrus.com]
> # Daniel Berger wrote:
> # > class Float
> # > def ==(other)
> # > self.to_s == other.to_s
> # > end
> # > end
> # Oh yes, nice one. This fulfills
> # 'from x==y and y==z follows x==z'
> # Unfortunately it does not fulfill some other properties one
>
> w a little help fr bigdecimal, a little goes a long long way
>
>> class Float
>> def to_dec
>> BigDecimal.new(self.to_s)
>> end
>> end
> => nil
>> class Fixnum
>> def to_dec
>> BigDecimal.new(self.to_s)
>> end
>> end
> => nil
>
>> x=0.06.to_dec
>> y=0.05.to_dec + 0.01.to_dec
>> x==y
> => true
>> z=0.02.to_dec+0.04.to_dec
>> y==z
> => true
>> z==y
> => true
>> x==z
> => true
>> z==x
> => true
--snip--
However (among other problems):
> x = (1.0/3.0).to_dec
> y = 1.0.to_dec / 3.0.to_dec
> x == y # => false
HTH,
Michael
|
|
0
|
|
|
|
Reply
|
michael.ulm (77)
|
9/4/2007 11:10:34 AM
|
|
From: Michael Ulm [mailto:michael.ulm@isis-papyrus.com]=20
# However (among other problems):
# > x =3D (1.0/3.0).to_dec
foul.. ^^^^^^^^^ is a float op and not a bigdecimal/to_dec. use atomic =
operations comparison, pls :)
# > y =3D 1.0.to_dec / 3.0.to_dec
that is more like it
# > x =3D=3D y # =3D> false
of course.
so consider eg,
irb(main):057:0> x =3D 1.0.to_dec / 3.0.to_dec
=3D> #<BigDecimal:b7d87acc,'0.3333333333 333333E0',16(24)>
irb(main):058:0> y =3D 2.0.to_dec / 6.0.to_dec
=3D> #<BigDecimal:b7d7d874,'0.3333333333 333333E0',16(24)>
irb(main):059:0> x =3D=3D y
=3D> true
kind regards -botp
|
|
0
|
|
|
|
Reply
|
botp (987)
|
9/5/2007 1:02:05 AM
|
|
Pe�a wrote:
> From: Michael Ulm [mailto:michael.ulm@isis-papyrus.com]
> # However (among other problems):
> # > x = (1.0/3.0).to_dec
>
> foul.. ^^^^^^^^^ is a float op and not a bigdecimal/to_dec. use atomic operations comparison, pls :)
>
--snip--
What about
> x = 1.0.to_dec / 3.0.to_dec
> y = x + x + x
> y == 1.0.to_dec # => false
?
HTH,
Michael
--
Michael Ulm
R&D Team
ISIS Information Systems Austria
tel: +43 2236 27551-542, fax: +43 2236 21081
e-mail: michael.ulm@isis-papyrus.com
Visit our Website: www.isis-papyrus.com
---------------------------------------------------------------
This e-mail is only intended for the recipient and not legally
binding. Unauthorised use, publication, reproduction or
disclosure of the content of this e-mail is not permitted.
This email has been checked for known viruses, but ISIS accepts
no responsibility for malicious or inappropriate content.
---------------------------------------------------------------
|
|
0
|
|
|
|
Reply
|
michael.ulm (77)
|
9/5/2007 6:33:12 AM
|
|
From: Michael Ulm [mailto:michael.ulm@isis-papyrus.com]=20
# > x =3D 1.0.to_dec / 3.0.to_dec
# > y =3D x + x + x
# > y =3D=3D 1.0.to_dec # =3D> false
hmm, i thought this was already answered by others.. gotta check..
irb(main):023:0* x=3D1.0.to_dec/3.0.to_dec
=3D> #<BigDecimal:b7e45e14,'0.3333333333 333333E0',16(24)>
irb(main):024:0> x+x+x =3D=3D 1.0.to_dec
=3D> true
kind regards -botp
|
|
0
|
|
|
|
Reply
|
botp (987)
|
9/6/2007 1:25:36 AM
|
|
Pe�a wrote:
> From: Michael Ulm [mailto:michael.ulm@isis-papyrus.com]
> # > x = 1.0.to_dec / 3.0.to_dec
> # > y = x + x + x
> # > y == 1.0.to_dec # => false
>
> hmm, i thought this was already answered by others.. gotta check..
>
> irb(main):023:0* x=1.0.to_dec/3.0.to_dec
> => #<BigDecimal:b7e45e14,'0.3333333333 333333E0',16(24)>
> irb(main):024:0> x+x+x == 1.0.to_dec
> => true
Strange, I tested this on two different machines and both gave false
to your last expression. Did you modify BigDecimal#== ?
Regards,
Michael
|
|
0
|
|
|
|
Reply
|
michael.ulm (77)
|
9/6/2007 11:07:58 AM
|
|
This is why I prefer to use fixed decimal. In your own private code,
it's easy enough to implement. You just decide how many "decimals" your
int's should have.
Getting correct programs using floats are really hard. Heck, MS Excell
don't even get Sum and Mean right. (Microsoft, usually, use naïve
algorithm's that don't take care of underflow and rounding errors).
--
Posted via http://www.ruby-forum.com/.
|
|
0
|
|
|
|
Reply
|
martialis (8)
|
9/6/2007 7:27:07 PM
|
|
From: Michael Ulm [mailto:michael.ulm@isis-papyrus.com]=20
# > From: Michael Ulm [mailto:michael.ulm@isis-papyrus.com]=20
# > irb(main):023:0* x=3D1.0.to_dec/3.0.to_dec
# > =3D> #<BigDecimal:b7e45e14,'0.3333333333 333333E0',16(24)>
# > irb(main):024:0> x+x+x =3D=3D 1.0.to_dec
# > =3D> true
#=20
# Strange, I tested this on two different machines and both gave false
# to your last expression. Did you modify BigDecimal#=3D=3D ?
yes. i just used one of the codes posted here.. not sure if it was even =
your suggested code though. nonetheless, what were you expecting? that =
1/3 can be represented exactly in decimal? :)
but i really want a way to override float literals, so i do not litter =
all those to_decs :)) Of course, floats has a lot of merits, but it =
gives too many surprises fr just a few dec samples. businesswise, it has =
little use.
kind regards -botp
|
|
0
|
|
|
|
Reply
|
botp (987)
|
9/7/2007 12:29:44 AM
|
|
|
43 Replies
33 Views
(page loaded in 0.388 seconds)
|