float is legacy

79
Float is Legacy Kenta Murata RubyConf 2011 1 Monday, October 10, 11

Upload: kenta-murata

Post on 28-May-2015

5.117 views

Category:

Technology


0 download

DESCRIPTION

My presentation in RubyConf 2011.You can see the description at http://rubyconf.org/presentations/33You can get the implementation proposed this presentation from https://github.com/mrkn/ruby/tree/decimal_rational_implementation

TRANSCRIPT

Page 1: Float is Legacy

Float is LegacyKenta Murata

RubyConf 2011

1Monday, October 10, 11

Page 2: Float is Legacy

http://www.flickr.com/photos/recompile_net/5951998279/

Kenta MurataCRuby committer

bigdecimal maintainer

OS X platform maintainer

Interested in number system

@mrkn

2Monday, October 10, 11

Page 3: Float is Legacy

https://twitter.com/#!/shyouhei/status/1198029834238074883Monday, October 10, 11

Page 4: Float is Legacy

https://twitter.com/#!/shyouhei/status/1198029834238074883Monday, October 10, 11

Page 5: Float is Legacy

http://www.flickr.com/photos/recompile_net/5951998279/

Kenta MurataCRuby committer

bigdecimal maintainer

OS X platform maintainer

Interested in number system

Ruby Sapporo

@mrkn

4Monday, October 10, 11

Page 6: Float is Legacy

Sapporo, Japanhttp://www.flickr.com/photos/muraken/6174655831

5Monday, October 10, 11

Page 7: Float is Legacy

Sapporo, Japanhttp://www.flickr.com/photos/irasally/4708650832/

6Monday, October 10, 11

Page 8: Float is Legacy

The RubyKaigi is finished.

7Monday, October 10, 11

Page 9: Float is Legacy

Regional RubyKaigi is continue.

8Monday, October 10, 11

Page 10: Float is Legacy

Sapporo RubyKaigi 04

in the next summer.

9Monday, October 10, 11

Page 11: Float is Legacy

Official informationwill be coming soon.

10Monday, October 10, 11

Page 12: Float is Legacy

Acknowledgement

Tatsuhiro Ujihisa, @ujmHootSuite Media, Inc.

Yoshimasa Niwa, @niwTwitter, Inc.

11Monday, October 10, 11

Page 13: Float is Legacy

Float is LegacyKenta Murata

RubyConf 2011

12Monday, October 10, 11

Page 14: Float is Legacy

Summary

Float requires us the advanced knowledge

Most rubyists don’t need Float

Rational is enough for us

Literal of decimal fraction interpreted as Rational makes us more happy

13Monday, October 10, 11

Page 15: Float is Legacy

Float class

14Monday, October 10, 11

Page 16: Float is Legacy

What is Float class?

A wrapper for C double.

Boxing a value of double.

Need to allocate an object to generate a new Float.

15Monday, October 10, 11

Page 17: Float is Legacy

Do you know C double?

Floating point number with double precision.

No concrete representation is specified.

Most current platforms employ IEEE754.

It is IEEE754 binary64 on these platforms.

There are platforms employing other spec.

16Monday, October 10, 11

Page 18: Float is Legacy

CRuby and JIS Ruby

Not requiring IEEE754.

17Monday, October 10, 11

Page 19: Float is Legacy

Floating point numbers

18Monday, October 10, 11

Page 20: Float is Legacy

The origin

NA = +6.022 141 79⇥ 10

23(±0.000 000 0030⇥ 10

23) [1/mol]

h = +6.626 069 57⇥ 10

�34(±0.000 000 0029⇥ 10

�34) [J s]

19Monday, October 10, 11

Page 21: Float is Legacy

The origin

NA = +6.022 141 79⇥ 10

23(±0.000 000 0030⇥ 10

23) [1/mol]

h = +6.626 069 57⇥ 10

�34(±0.000 000 0029⇥ 10

�34) [J s]

sign

19Monday, October 10, 11

Page 22: Float is Legacy

The origin

NA = +6.022 141 79⇥ 10

23(±0.000 000 0030⇥ 10

23) [1/mol]

h = +6.626 069 57⇥ 10

�34(±0.000 000 0029⇥ 10

�34) [J s]

fraction part

sign

19Monday, October 10, 11

Page 23: Float is Legacy

The origin

NA = +6.022 141 79⇥ 10

23(±0.000 000 0030⇥ 10

23) [1/mol]

h = +6.626 069 57⇥ 10

�34(±0.000 000 0029⇥ 10

�34) [J s]

exponent partfraction part

sign

19Monday, October 10, 11

Page 24: Float is Legacy

The origin

NA = +6.022 141 79⇥ 10

23(±0.000 000 0030⇥ 10

23) [1/mol]

h = +6.626 069 57⇥ 10

�34(±0.000 000 0029⇥ 10

�34) [J s]

exponent part:fraction part:

sign: s 2 {0, 1}

0 f Bn � 1

emin

e� q emax

20Monday, October 10, 11

Page 25: Float is Legacy

Floating point numbersNumbers can be identified by (s, e, f ).

Represent approximation of real numbers.

Float types can be described by B, N, q, emin, and emax.

B is the base number of the exponent part.

N is the number of digits in the fraction part.

q is the bias for the exponent part.

emax and emin specify the limit of the exponent part.

21Monday, October 10, 11

Page 26: Float is Legacy

(s, e, f) = (�1)s ⇥ f

BN⇥Be�q

22Monday, October 10, 11

Page 27: Float is Legacy

e.g. IEEE754 binary64

B = 2

N = 53

q = 1,023

emin = –1,022

emax = +1,023

The maximum positive:1.797 693 134 862 315 7 ×10+308

The minimum nonzero positive:2.225 073 858 507 201 4 ×10–308

23Monday, October 10, 11

Page 28: Float is Legacy

(s, e, f) = (�1)s ⇥ f

BN⇥Be�q

24Monday, October 10, 11

Page 29: Float is Legacy

e.g. IEEE754 decimal64

B = 10

N = 16

q = 398

emin = –383

emax = +384

The maximum positive:9.999 999 999 999 999 ×10+384

The minimum nonzero positive:0.000 000 000 000 001 ×10–383

25Monday, October 10, 11

Page 30: Float is Legacy

e.g. IBM’s double precision

B = 16

N = 56

q = 64

emin = –64

emax = +63

The maximum positive:7.237 005 577 332 262 11 ×10+75

The minimum nonzero positive:5.397 605 346 934 027 89 ×10–79

26Monday, October 10, 11

Page 31: Float is Legacy

Floating point numbersNumbers can be identified by (s, e, f ).

Represent approximation of real numbers.

Float types can be described by B, N, q, emin, and emax.

B is the base number of the exponent part.

N is the number of digits in the fraction part.

q is the bias for the exponent part.

emax and emin specify the limit of the exponent part.

27Monday, October 10, 11

Page 32: Float is Legacy

Every float is approximation

28Monday, October 10, 11

Page 33: Float is Legacy

Every float is approximation

0 3/2–1

28Monday, October 10, 11

Page 34: Float is Legacy

Every float is approximation

0 3/2–1

0.0 1.5–1.0

{ { {28Monday, October 10, 11

Page 35: Float is Legacy

Every float is approximation

0 3/2–1

0.0 1.5–1.0

{ { {28Monday, October 10, 11

Page 36: Float is Legacy

Every float is approximation

0 3/2–1

0.0 1.5–1.0

{ { {28Monday, October 10, 11

Page 37: Float is Legacy

Every float is approximation

We should think:

There are no numbers represented exactly.

Floating point numbers always include errors.

Magnitude of errors depend on B, N, and e.

29Monday, October 10, 11

Page 38: Float is Legacy

Why including errors?

Unavoidable issue from place-value notationwith finite digits rounding.

Very few values can be specified exactly.

We shouldn’t expect that a given value is exact.

30Monday, October 10, 11

Page 39: Float is Legacy

How many decimal fractions can be exactly represented in the form of binary fraction?

31Monday, October 10, 11

Page 40: Float is Legacy

32Monday, October 10, 11

Page 41: Float is Legacy

Decimal form:

(0.1234)10 =(1234)10

104

32Monday, October 10, 11

Page 42: Float is Legacy

Decimal form:

Binary form:

(0.10111)2 =(10111)2

25

(0.1234)10 =(1234)10

104

32Monday, October 10, 11

Page 43: Float is Legacy

Decimal form:

Binary form:

(0.10111)2 =(10111)2

25

(0.1234)10 =(1234)10

104

0.b1b2 · · · bn =(b1b2 · · · bn)2

2n

0.d1d2 · · · dm =(d1d2 · · · dm)10

10m

32Monday, October 10, 11

Page 44: Float is Legacy

Decimal form:

Binary form:

(0.10111)2 =(10111)2

25

(0.1234)10 =(1234)10

104

0.b1b2 · · · bn =(b1b2 · · · bn)2

2n

0.d1d2 · · · dm =(d1d2 · · · dm)10

10m

32Monday, October 10, 11

Page 45: Float is Legacy

(d1d2 · · · dm)1010m

=(d1d2 · · · dm)10

2m 5m=

C 5m

2m 5m=

C

2m

33Monday, October 10, 11

Page 46: Float is Legacy

1.0

0.5

0.05 10 15 20 25 300

The ratio of inexact numbers

The ratio of exact numbers

The number of decimal digits

34Monday, October 10, 11

Page 47: Float is Legacy

1.0

0.5

0.05 10 15 20 25 300

The ratio of inexact numbers

The ratio of exact numbers

17

The number of decimal digits

34Monday, October 10, 11

Page 48: Float is Legacy

1.0

0.5

0.05 10 15 20 25 300

The ratio of inexact numbers

The ratio of exact numbersIEEE

754 bina

ry64

17

The number of decimal digits

34Monday, October 10, 11

Page 49: Float is Legacy

Decimal in Binary

A N-digit decimal notation is exactly represented in binary notation only if its numerator divisible by 5N.

The ratio of N-digit decimal fractions exactly represented as binary fraction is 1 / 5N.

In IEEE754 binary64, almost all numbers are inexact.

35Monday, October 10, 11

Page 50: Float is Legacy

Floating-point arithmetics

add, sub, mul, div, sqrt, ...

These operations work with errors.

Please read detail description:

“What Every Computer Scientist Should Know About Floating-Point Arithmetic”

36Monday, October 10, 11

Page 51: Float is Legacy

Decimal fraction of Ruby

37Monday, October 10, 11

Page 52: Float is Legacy

What’s the problem?

Ruby interprets literals of decimal fraction as Float

The following three numbers are Float, so they have errors.

1.0

1.2

0.42e+12

38Monday, October 10, 11

Page 53: Float is Legacy

The issues from Float

There are many issues about Float reported to redmine.ruby-lang.org

They are caused by that Ruby interpretes the literals of decimal fraction as Float, I think.

Do you know these issues?

39Monday, October 10, 11

Page 54: Float is Legacy

http://redmine.ruby-lang.org/issues/457640Monday, October 10, 11

Page 55: Float is Legacy

Demonstration

41Monday, October 10, 11

Page 56: Float is Legacy

$ ruby -vruby 1.9.4dev (2011-09-28 trunk 33354) [x86_64-darwin10.8.0]$ irb --simple-prompt>> (1.0 .. 12.7).step(1.3).to_a=> [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.700000000000001]>> (1.0 ... 128.4).step(18.2).to_a=> [1.0, 19.2, 37.4, 55.599999999999994, 73.8, 92.0, 110.19999999999999, 128.39999999999998]>> (1.0 ... 128.4).step(18.2).to_a.size=> 8>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a=> [1, (96/5), (187/5), (278/5), (369/5), (92/1), (551/5)]>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a.size=> 7

42Monday, October 10, 11

Page 57: Float is Legacy

$ ruby -vruby 1.9.4dev (2011-09-28 trunk 33354) [x86_64-darwin10.8.0]$ irb --simple-prompt>> (1.0 .. 12.7).step(1.3).to_a=> [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.700000000000001]>> (1.0 ... 128.4).step(18.2).to_a=> [1.0, 19.2, 37.4, 55.599999999999994, 73.8, 92.0, 110.19999999999999, 128.39999999999998]>> (1.0 ... 128.4).step(18.2).to_a.size=> 8>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a=> [1, (96/5), (187/5), (278/5), (369/5), (92/1), (551/5)]>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a.size=> 7

The last value of the array should be equal to the end of the range

43Monday, October 10, 11

Page 58: Float is Legacy

$ ruby -vruby 1.9.4dev (2011-09-28 trunk 33354) [x86_64-darwin10.8.0]$ irb --simple-prompt>> (1.0 .. 12.7).step(1.3).to_a=> [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.700000000000001]>> (1.0 ... 128.4).step(18.2).to_a=> [1.0, 19.2, 37.4, 55.599999999999994, 73.8, 92.0, 110.19999999999999, 128.39999999999998]>> (1.0 ... 128.4).step(18.2).to_a.size=> 8>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a=> [1, (96/5), (187/5), (278/5), (369/5), (92/1), (551/5)]>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a.size=> 7

Some elements include errors

44Monday, October 10, 11

Page 59: Float is Legacy

$ ruby -vruby 1.9.4dev (2011-09-28 trunk 33354) [x86_64-darwin10.8.0]$ irb --simple-prompt>> (1.0 .. 12.7).step(1.3).to_a=> [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.700000000000001]>> (1.0 ... 128.4).step(18.2).to_a=> [1.0, 19.2, 37.4, 55.599999999999994, 73.8, 92.0, 110.19999999999999, 128.39999999999998]>> (1.0 ... 128.4).step(18.2).to_a.size=> 8>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a=> [1, (96/5), (187/5), (278/5), (369/5), (92/1), (551/5)]>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a.size=> 7

The array size is one larger than the correct size

45Monday, October 10, 11

Page 60: Float is Legacy

Range#step with Float

The first case

The last value of the array is not equal to the end of the range.

The second case

Some elements include errors.

The array size is one larger than the right size.

46Monday, October 10, 11

Page 61: Float is Legacy

Rational with decimal notation

Introducing one flag into a Rational object.

The flag represents a Rational seems which fraction or decimal.

If the flag is true, a Rational is converted decimal string by to_s.

47Monday, October 10, 11

Page 62: Float is Legacy

Literal for Rational with decimal notation

Simple change for parser.

Interpreting literal of decimal fraction without exponent as Rational with decimal notation.

Literal of decimal fraction with exponent stays on Float.

48Monday, October 10, 11

Page 63: Float is Legacy

Demonstrationusing the patched Rubyhttps://github.com/mrkn/ruby/tree/decimal_rational_implementation

49Monday, October 10, 11

Page 64: Float is Legacy

$ ruby -vruby 1.9.4dev (2011-09-28 trunk 33354) [x86_64-darwin10.8.0]$ irb --simple-prompt>> (1.0 .. 12.7).step(1.3).to_a=> [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.7]>> (1.0 .. 12.7).step(1.3).map(&:class)=> [Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational]>> (1.0 ... 128.4).step(18.2).to_a=> [1.0, 19.2, 37.4, 55.6, 73.8, 92.0, 110.2]>> (1.0 ... 128.4).step(18.2).to_a.size=> 7>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a=> [1, (96/5), (187/5), (278/5), (369/5), (92/1), (551/5)]>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a.size=> 7

50Monday, October 10, 11

Page 65: Float is Legacy

$ ruby -vruby 1.9.4dev (2011-09-28 trunk 33354) [x86_64-darwin10.8.0]$ irb --simple-prompt>> (1.0 .. 12.7).step(1.3).to_a=> [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.7]>> (1.0 .. 12.7).step(1.3).map(&:class)=> [Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational]>> (1.0 ... 128.4).step(18.2).to_a=> [1.0, 19.2, 37.4, 55.6, 73.8, 92.0, 110.2]>> (1.0 ... 128.4).step(18.2).to_a.size=> 7>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a=> [1, (96/5), (187/5), (278/5), (369/5), (92/1), (551/5)]>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a.size=> 7

The last value of the array is equal to the end of the range.

51Monday, October 10, 11

Page 66: Float is Legacy

$ ruby -vruby 1.9.4dev (2011-09-28 trunk 33354) [x86_64-darwin10.8.0]$ irb --simple-prompt>> (1.0 .. 12.7).step(1.3).to_a=> [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.7]>> (1.0 .. 12.7).step(1.3).map(&:class)=> [Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational]>> (1.0 ... 128.4).step(18.2).to_a=> [1.0, 19.2, 37.4, 55.6, 73.8, 92.0, 110.2]>> (1.0 ... 128.4).step(18.2).to_a.size=> 7>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a=> [1, (96/5), (187/5), (278/5), (369/5), (92/1), (551/5)]>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a.size=> 7

All elements in the array is Rational rather than Float.

52Monday, October 10, 11

Page 67: Float is Legacy

$ ruby -vruby 1.9.4dev (2011-09-28 trunk 33354) [x86_64-darwin10.8.0]$ irb --simple-prompt>> (1.0 .. 12.7).step(1.3).to_a=> [1.0, 2.3, 3.6, 4.9, 6.2, 7.5, 8.8, 10.1, 11.4, 12.7]>> (1.0 .. 12.7).step(1.3).map(&:class)=> [Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational, Rational]>> (1.0 ... 128.4).step(18.2).to_a=> [1.0, 19.2, 37.4, 55.6, 73.8, 92.0, 110.2]>> (1.0 ... 128.4).step(18.2).to_a.size=> 7>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a=> [1, (96/5), (187/5), (278/5), (369/5), (92/1), (551/5)]>> (1 ... 1284.quo(10)).step(182.quo(10)).to_a.size=> 7

The result array size is correct.

53Monday, October 10, 11

Page 68: Float is Legacy

Benchmarking

Comparing Float, Rational, and C double.

Experimental environment:

MacBook Pro 15in (Mid 2010)

Core i7 2.66 GHz

Ruby 1.9.4dev (r33300) with gcc-4.2 -O3

C with llvm-gcc -O0

54Monday, October 10, 11

Page 69: Float is Legacy

Benchmarking codes

Ruby code

https://gist.github.com/1253088

C code

https://gist.github.com/1253090

55Monday, October 10, 11

Page 70: Float is Legacy

0 [s]

0.75 [s]

1.5 [s]

2.25 [s]

3 [s]

1M additions 1M subtractions 1M multiplications

Based on ruby-1.9.4dev (r33300)

Float Rational C double

0.37

2.16

0.73

2.17

0.70

1.78

0.00777 0.00670 0.00770

56Monday, October 10, 11

Page 71: Float is Legacy

0 [s]

0.003 [s]

0.005 [s]

0.008 [s]

0.01 [s]

1M additions 1M subtractions 1M multiplications

Based on ruby-1.9.4dev (r33300)

Float Rational C double

0.37 2.16 0.73 2.17 0.70 1.78

0.00777

0.00670

0.00770

57Monday, October 10, 11

Page 72: Float is Legacy

Benchmarking summary

Rational is 2-5 times slower than Float.

Float is 2-digit order slower than C double.

C is amazingly fast.

58Monday, October 10, 11

Page 73: Float is Legacy

If you said Rational is slow,Float isn’t as fast as your expect.

59Monday, October 10, 11

Page 74: Float is Legacy

Rational vs Float

60Monday, October 10, 11

Page 75: Float is Legacy

Rational vs Float

61Monday, October 10, 11

Page 76: Float is Legacy

Rational vs Float

Exact computation is required by domains such as finance.

Float is required by scientific computation.

61Monday, October 10, 11

Page 77: Float is Legacy

Rational vs Float

Exact computation is required by domains such as finance.

Float is required by scientific computation.

Other aspects indepenend of whether Rational or Float.

61Monday, October 10, 11

Page 78: Float is Legacy

Conclusion

Float is difficult, troublesome, and not human oriented.

Rational is easy to understand, and human oriented.

It makes us more happy that Ruby interprets literal of decimal fraction as Rational.

62Monday, October 10, 11

Page 79: Float is Legacy

Float is Legacy

63Monday, October 10, 11