Microrant on Ruy's Math Skills

#1

So simple…

1.1 - 1.to_f == 0.1

false

(rumble) (rumble) Pathetic!

#2

On Sat, Jan 21, 2012 at 8:06 AM, Intransition removed_email_address@domain.invalid
wrote:

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

#3

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

So simple…

1.1 - 1.to_f == 0.1

false

(rumble) (rumble) Pathetic!

http://stackoverflow.com/questions/2595666/why-would-ruby-fail-equality-on-2-floats-that-appear-the-same

#4

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

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

#5

On Jan 21, 2012 9:34 AM, “Gary W.” removed_email_address@domain.invalid wrote:

Decimal literals (e.g. 1.1) can’t always be represented exactly as binary
floats:
=> 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?

#6

On Sat, Jan 21, 2012 at 9:08 AM, Yossef M.
removed_email_address@domain.invalidwrote:

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?

If I were designing a language today 1.1 would be a decimal type ala
BigDecimal and I’d have some other syntax like 1.1f for floats.

#7

On Sat, Jan 21, 2012 at 9:38 AM, Su Zhang
removed_email_address@domain.invalidwrote:

Native floating point operations are usually hardware accelerated by the
underlying machine’s FPU whereas libraries like BigDecimal emulate floating
point operations by software.

For all those people doing high performance math in Ruby…

#8

So they can drop a billion transistors on a chip, have implemented 3D
pipelines and video codec optimizations in hardware, but no one ever
thought thay maybe it would be a good idea to support accurate base-10
math
on the die?

Bankers and Engineers must not hang about in the same circles at all.

#9

On 1/21/2012 12:08 PM, Yossef M. wrote:

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?

Native floating point operations are usually hardware accelerated by the
underlying machine’s FPU whereas libraries like BigDecimal emulate
floating point operations by software.

#10

Yea, I just don’t expect Ruby’s first priority to be speed. I tend to
expect POLS, which I would think would lead to giving priority to
precision
(which I suppose means BigDecimal) but allow the option for faster
floating
point if needed.

#11

On Sun, Jan 22, 2012 at 02:08, Intransition removed_email_address@domain.invalid wrote:

Yea, I just don’t expect Ruby’s first priority to be speed. I tend to
expect POLS, which I would think would lead to giving priority to precision
(which I suppose means BigDecimal) but allow the option for faster floating
point if needed.

Since you mentioned POLS, the standard thing to remember is that it’s
Matz’s surprise, once you understand Matz’s view of things. :slight_smile: Aside
from
that, though, if you understand that 0.9 is a floating point number, and
you’re coming from other languages where this is the case, then you
understand what it means to compare 0.9 to another number which displays
as
0.9.

“%.60f” % 0.9
#=> “0.900000000000000022204460492503130808472633361816406250000000”

But I also recognise that it will throw people completely new to
programming who have no appreciation for what’s happening beneath
various
levels of abstraction created by the language when the issue arises.

Also, this is probably obligatory:
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html (I’m
surprised it hasn’t been mentioned yet!)

(For the POLS thing in Ruby:
https://en.wikipedia.org/wiki/Ruby_(programming_language)#Philosophy )

#12

On Sat, Jan 21, 2012 at 8:06 AM, Intransition removed_email_address@domain.invalid
wrote:

So simple…

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.

#13

On Sat, Jan 21, 2012 at 10:06 PM, Intransition removed_email_address@domain.invalid
wrote:

1.1 - 1.to_f == 0.1

false

(rumble) (rumble) Pathetic!

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

kind regards -botp

#14

: Bankers and Engineers must not hang about in the same circles at all.

True.

http://speleotrove.com/decimal/decifaq.html

#15

On Sun, Jan 22, 2012 at 3:03 AM, Intransition removed_email_address@domain.invalid
wrote:

So they can drop a billion transistors on a chip, have implemented 3D
pipelines and video codec optimizations in hardware, but no one ever thought
thay maybe it would be a good idea to support accurate base-10 math on the
die?

Floating point math with binary representation of numbers is more
efficient than with decimal because you need less bits for
representing the same number. And there is a standard for floating
point arithmetic which clearly defines how it must be done (i.e. base
2):

http://en.wikipedia.org/wiki/Floating_point_number#IEEE_754:_floating_point_in_modern_computers

So BigDecimal is always the special case while the standard is binary.
It’s good that Ruby does not digress from this standard because if it
would do this could have dramatic effects (on performance for
example).

Kind regards

robert

#16

Thomas S. 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.

#17

On Mon, Jan 23, 2012 at 11:33 AM, Peter V.
<removed_email_address@domain.invalid

wrote:

die?
So BigDecimal is always the special case while the standard is binary.

amount = BigDecimal.new(“15.5”)

to

amount = 15.5B

Maybe

15.5D

is better naming (maps to “Decimal” and the %d of format string).

Peter

#18

On Mon, Jan 23, 2012 at 9:29 AM, Robert K.
removed_email_address@domain.invalidwrote:

representing the same number. And there is a standard for floating

Feature request:

Based on this discussion, it would actually be useful to me if I could
shorten this:

amount = BigDecimal.new(“15.5”)

to

amount = 15.5B

Then we could also answer future questions about

“How come 1.1 - 1.0 != 0.1 ??”

with

“1.1B - 1B == 0.1B”

HTH,

Peter

#19

On Mon, Jan 23, 2012 at 11:35 AM, Peter V.
removed_email_address@domain.invalid wrote:

On Mon, Jan 23, 2012 at 11:33 AM, Peter V. <removed_email_address@domain.invalid

Feature request:

Based on this discussion, it would actually be useful to me if I could
shorten this:

amount = BigDecimal.new(“15.5”)

to

amount = 15.5B

Bad idea IMHO because this requires a parser change and also makes all
programs implicitly require “bigdecimal” which is usually not needed.

Maybe

15.5D

is better naming (maps to “Decimal” and the %d of format string).

Or

amount = 15.4.to_bd
amount = 15.4.to_decimal
amount = 15.4.to_dec
amount = BD(15.4)

Kind regards

robert

#20

On Mon, Jan 23, 2012 at 4:40 AM, Robert K.
removed_email_address@domain.invalidwrote:

amount = BigDecimal.new(“15.5”)
15.5D

But this forces it to go through a float which is where the inaccuracies
come in.