Microrant on Ruy's Math Skills

So simple...

  1.1 - 1.to_f == 0.1
  >> false

(*rumble*) (*rumble*) Pathetic!

So simple...

  1.1 - 1.to_f == 0.1
  >> false

Your beef is with floating point.

Yeah it's lame.
The currency gem I think is a work around this, iirc.

Andrew

···

On Sat, Jan 21, 2012 at 8:06 AM, Intransition <transfire@gmail.com> wrote:

(*rumble*) (*rumble*) Pathetic!

···

On 1/21/2012 9:06 AM, Intransition wrote:

So simple...

1.1 - 1.to_f == 0.1
>> false

(*rumble*) (*rumble*) Pathetic!

So simple...

  1.1 - 1.to_f == 0.1
  >> false

(*rumble*) (*rumble*) Pathetic!

Decimal literals (e.g. 1.1) can't always be represented exactly as binary floats:

"%.40f" % 1.1

=> "1.1000000000000000888178419700125232338905"

"%.40f" % 1.0

=> "1.0000000000000000000000000000000000000000"

Use BigDecimal if you need exact precision:

require 'bigdecimal'

=> true

BigDecimal.new("1.1") - BigDecimal.new("1.0")

=> #<BigDecimal:7fc50ea75ff0,'0.1E0',9(36)>

puts BigDecimal.new("1.1") - BigDecimal.new("1.0")

0.1

···

On Jan 21, 2012, at 9:06 AM, Intransition wrote:

look at the bright side, trans. you could possibly include one (soln)
in your facets.. maybe include some epsilon there
...

kind regards -botp

···

On Sat, Jan 21, 2012 at 10:06 PM, Intransition <transfire@gmail.com> wrote:

1.1 - 1.to_f == 0.1
>> false

(*rumble*) (*rumble*) Pathetic!

I always figured if you needed that stuff, you have an avenue to get it:

require 'mathn'
1 / 3 # => (1/3)

But leaving normal fast floating point math that people are used to from
everywhere else seems like an obvious default.

···

On Sat, Jan 21, 2012 at 8:06 AM, Intransition <transfire@gmail.com> wrote:

So simple...

  1.1 - 1.to_f == 0.1
  >> false

(*rumble*) (*rumble*) Pathetic!

Thomas Sawyer wrote in post #1041913:

So simple...

  1.1 - 1.to_f == 0.1
  >> false

(*rumble*) (*rumble*) Pathetic!

Real programmers do not compare floats for equality.

···

--
Posted via http://www.ruby-forum.com/\.

FWIW, ruby-core member Kenta Murata has a proposal to replace Float with
BigDecimal. Here are his slides from rubyconf on the subject:

Sorry if this has been mentioned already.

pete

  1.1 - 1.to_f == 0.1
  >> false

(*rumble*) (*rumble*) Pathetic!

Agree.

At least with 1.9.2 it's possible to tell more easily why this occurs:

1.1-1

=> 0.10000000000000009

0.1

=> 0.1

So some progress has been made.
But I'm with you I'd prefer the default to be rational or bigdecimal,
and you have to use
1.1f

for floats. Then you still have speed available, but not lose precision
in the default case. But that's just me, and apparently it's too big of
a change for Matz to swallow I suppose...
-roger-

···

--
Posted via http://www.ruby-forum.com/\.

Hi all,

Such a large discussion from a simple initial post that was, in all likelihood, an attempt to troll for as many responses as possible. It looks like it has been wildly successful.

Perhaps a response like this would have been appropriate:

"Floats in Ruby are represented using the floating point numbers provided by the underlying system, which are generally base 2 floating point numbers, as per IEEE 754. They have advantages and disadvantages that are worth being aware of, including loss of precision for certain operations and values. This means that you cannot rely on testing for equality in certain cases, and it may be more appropriate to check to see if the result is within a certain epsilon. If the disadvantages are not suitable for your problem domain or use case, you will have to use a different numeric representation system more suited to your problem. All representation systems have their own strengths and weaknesses. BigDecimal may be more suitable than float in this case. A web search for 'floating point representation' will provided much additional useful information."

In any form of software development you need to be aware of the capabilities and limitations of the systems that you use, and in many cases make an informed decision based on a set of potential systems. To remain wilfully ignorant of these systems, and then cry "pathetic", is disingenuous. To subsequently push for language changes based on such a shaky foundation is ludicrous. There are far better ways to stimulate genuine discussion on an genuinely interesting topic than through a deliberately inflammatory initial posting and comparable followups.

IMHO.

Garth

···

On 22/01/12 00:36, Intransition wrote:
> So simple...
>
> 1.1 - 1.to_f == 0.1
> >> false
>
> (*rumble*) (*rumble*) Pathetic!

(2) The amount of emotion and defensiveness around this issue is
staggering. It is the very definition of a religious argument. On one
side are people who think "math should work like I learned in grade
school," on the other are people who think "math does work like I
learned in college" (and the subset of those saying, "if you haven't
had my level of training then you are stupid"), and then there a bunch
of people in the middle saying, "you're both right, sort of!"

Well. I have always been bad in Math.

But when I see something like:

x = 1.1

Then i assume that x will be exactly 1.1

That would even by MY own principle of least surprise.

Now I read that, due to the way how Floats are handled on
computers, this is only an approximation.

And I am sad. Because it shows that computers are not perfect
at all.

Because I want to think that Math is more elegant and more
precise than it should have to deal with a

1.100000000000000088817841970012523233890533447265625000000000

instead.

Where is the elegance in that number? It is as if someone is trying
to add some insignificant numbers to Infinity ... but of course
once done, these are no longer insignificant! They are now significant
and just rounded!

There goes a beautiful mind. :frowning:

···

--
Posted via http://www.ruby-forum.com/\.

Thomas Sawyer wrote in post #1041913:

So simple...
  1.1 - 1.to_f == 0.1
  >> false

Does Rails scale?

It's a silly question.

The person asking the question does not understand the problem that s/he
is attempting to solve.

This thread reminds me of that.

Did the OP provide any context for the problem, other than Pi, 1/3,
Infinity, 0.1 are just approximations in the computer world?

For those of you that are now “jaded” behind this new found knowledge,
please consider, the slide rule was accurate enough to land humans on
the moon.

Good god! What problem are you trying to solve?

The floating point capability on modern low-end hardware is
exceptionally fantastic.

One of the most important performance metrics is generally considered to
be floating point operations per second.

Finally, keep in mind many of the people involved in designing and
implementing these standards are smarter than you :wink:

···

--
Posted via http://www.ruby-forum.com/\.

it's stuff like this that suggest that our interpreter needs to suggest
possible, likely outcomes to executed malformed code, and try to find a
way to parse it, or scavenge it for memetic information about possible
code execution protocols. Most people are still coding for one core. You
need to give your cores names and get them to talk to each other. I
don't have the information or computer science degree to do so. Oh well,
at least I have my positional numbering system.

Attachments:
http://www.ruby-forum.com/attachment/6984/256_1.txt
http://www.ruby-forum.com/attachment/6985/base11.txt

···

--
Posted via http://www.ruby-forum.com/.

> So simple...
>
> 1.1 - 1.to_f == 0.1
> >> false
>
> (*rumble*) (*rumble*) Pathetic!

Decimal literals (e.g. 1.1) can't always be represented exactly as binary

floats:

>> "%.40f" % 1.1
=> "1.1000000000000000888178419700125232338905"
>> "%.40f" % 1.0
=> "1.0000000000000000000000000000000000000000"
>>

Use BigDecimal if you need exact precision:

>> require 'bigdecimal'
=> true
>> BigDecimal.new("1.1") - BigDecimal.new("1.0")
=> #<BigDecimal:7fc50ea75ff0,'0.1E0',9(36)>
>> puts BigDecimal.new("1.1") - BigDecimal.new("1.0")
0.1

This problem comes up from time to time, sometimes from people I'd expect
to know better than to ask. And the answer is always the same: that's how
floats work. And there's usually the same suggestion of using BigDecimal
(or something similar).

Since this time I'm waiting for someone and rather bored, I thought I'd see
how this goes. What's the real benefit of using floats? Why doesn't Ruby
actually use BigDecimal for things like this?

···

On Jan 21, 2012 9:34 AM, "Gary Wright" <gwtmp01@mac.com> wrote:

On Jan 21, 2012, at 9:06 AM, Intransition wrote:

--
-yossef

FWIW, ruby-core member Kenta Murata has a proposal to replace Float with
BigDecimal. Here are his slides from rubyconf on the subject:

Float is Legacy | PPT

This is very encouraging. I haven't been able to find the time, but maybe
introducing dual fix point might be viable?
google for LNCS 3203 - Dual Fixed-Point: An Efficient Alternative to
Floating
A pdf of that article should be available.

Andrew McElroy

···

On Mon, Jan 23, 2012 at 2:47 PM, Pete Higgins <pete@peterhiggins.org> wrote:

Sorry if this has been mentioned already.

pete

I does and it's broken! LOL!

(1) I love this thread! Though every time I open it, I think some poor
guy named Ruy needs a math tutor...

(2) The amount of emotion and defensiveness around this issue is
staggering. It is the very definition of a religious argument. On one
side are people who think "math should work like I learned in grade
school," on the other are people who think "math does work like I
learned in college" (and the subset of those saying, "if you haven't
had my level of training then you are stupid"), and then there a bunch
of people in the middle saying, "you're both right, sort of!"

(3) I spend a lot of time teaching people programming, not writing
statistical algorithms, and I've written a unit testing library that
aims to be as unobtrusive as possible, so my main concern is to
minimize surprise while not undermining correctness. So naming my
method "close_to?" allows me to dodge the religious question "what is
equality?" and focus on getting noobies to understand just enough
complicated math to get their tests to pass, which basically amounts
to the lesson "floats are weird sometimes".

I do think it's important that Ruby Float == keeps working exactly
like C == and JavaScript == (kinda) and Python == though.

Or, what Yossef and Gavin said: "there are two different concerns at play
here. One is the standard problem with IEEE floating-point representation.
The other is deciding whether one number is "close enough" to another. One
of these could be the concern of a programming language, while the other
would be the concern of a particular program."

(4) Gavin, I *did* follow your message to the end, and the code helped
me really get your point. I also like Whitestone (I mean, "I Lk W")
and I might steal some of your comparators. Allow me to return the
favor by teaching you that Github supports line numbers in its URLs,
e.g.

(5) How tragic is it that C broke a mathematical notation that had
worked just fine for hundreds of years and chose to define "=" as
assignment instead of equality? Amirite? Who's with me? :slight_smile:

···

--
Alex Chaffee - alex@stinky.com
http://alexchaffee.com
http://twitter.com/alexch

I don't think it was intended to troll, and Trans definitely understands
IEEE 754 floats. He just thinks Ruby should move beyond them.

Personally, I rarely ever use them, because of these issues. They are
unsuitable for more uses than they are suitable for, and they contradict
the idea that abstractions shouldn't leak implementation. OTOH, they're
fast and ubiquitous. So I'm not very opinionated either way, but I think
it's a discussion worth having.

···

On Thu, Jan 26, 2012 at 6:05 PM, Garthy D < garthy_lmkltybr@entropicsoftware.com> wrote:

Hi all,

Such a large discussion from a simple initial post that was, in all
likelihood, an attempt to troll for as many responses as possible. It looks
like it has been wildly successful.

Perhaps a response like this would have been appropriate:

"Floats in Ruby are represented using the floating point numbers provided
by the underlying system, which are generally base 2 floating point
numbers, as per IEEE 754. They have advantages and disadvantages that are
worth being aware of, including loss of precision for certain operations
and values. This means that you cannot rely on testing for equality in
certain cases, and it may be more appropriate to check to see if the result
is within a certain epsilon. If the disadvantages are not suitable for your
problem domain or use case, you will have to use a different numeric
representation system more suited to your problem. All representation
systems have their own strengths and weaknesses. BigDecimal may be more
suitable than float in this case. A web search for 'floating point
representation' will provided much additional useful information."

In any form of software development you need to be aware of the
capabilities and limitations of the systems that you use, and in many cases
make an informed decision based on a set of potential systems. To remain
wilfully ignorant of these systems, and then cry "pathetic", is
disingenuous. To subsequently push for language changes based on such a
shaky foundation is ludicrous. There are far better ways to stimulate
genuine discussion on an genuinely interesting topic than through a
deliberately inflammatory initial posting and comparable followups.

IMHO.

Garth

Regardless of the problems and advantages of the underlying
representation, and even in full knowledge of it, it is not pathetic
to think a modern language, one that seeks to please humans before
computers, should be able to recognise the truth of (1.1 - 1.0 ==
0.1). I do agree that wilful ignorance is probably never a good
thing, but I give Mr Intransition the benefit of the doubt. It was
advertised as a "rant", not the sum of his knowledge.

One possible change that has been mentioned at least a couple of times is:

   1.1 - 1.0 == 0.1
      # -> true, using programmer-friendly representation like BigDecimal

   1.1f - 1.0f == 0.1f
      # -> false; the programmer has explicitly chosen to use
computer-friendly floats

Of course, with coercion, the second example could simply be:
    1.1f - 1.0 == 0.1 # -> false

Such a language change could be debated and rejected, but it is not
self-evidently on shaky foundations and it is certainly not ludicrous.

There may be difficulties associated with designing and implementing
that particular idea, but it appear to me to be quite consistent with
Ruby as a whole.

Gavin

···

On Fri, Jan 27, 2012 at 11:05 AM, Garthy D <garthy_lmkltybr@entropicsoftware.com> wrote:

To remain wilfully
ignorant of these systems, and then cry "pathetic", is disingenuous. To
subsequently push for language changes based on such a shaky foundation is
ludicrous.

It's a direct consequence of trying to fit certain numbers into a binary
representation. You can work through this without a computer at all, just
the mathematics around trying to fit certain numbers into fixed-length
representations in some model; the computer is actually incidental here, to
an extent.

If it weren't 1.1 but were instead an irrational, such as sqrt(2), would
you still think it's a failure of a computer that you can't store its
infinite, non-recurring digits into a computer?

The mathematics behind it *is* precise. It's just that you're assuming one
finite mathematical model to be an infinite model catered to matching
symbolic manipulation. Is that mismatch unexpected to absolute beginners?
Most likely. Once you understand the model, though, there's nothing bizarre
happening. You haven't lost some intrinsic beauty. It's the model.

···

On Fri, Jan 27, 2012 at 04:13, Marc Heiler <shevegen@linuxmail.org> wrote:

x = 1.1

Then i assume that x will be exactly 1.1

That would even by MY own principle of least surprise.

Now I read that, due to the way how Floats are handled on
computers, this is only an approximation.

And I am sad. Because it shows that computers are not perfect
at all.