[#46105] [ruby-trunk - Feature #6687][Open] Enumerable#with — "merborne (kyo endo)" <redmine@...>

14 messages 2012/07/02

[#46133] [ruby-trunk - Feature #6688][Open] Object#replace — "prijutme4ty (Ilya Vorontsov)" <prijutme4ty@...>

24 messages 2012/07/03

[#46160] [ruby-trunk - Feature #6693][Open] Don't warn for unused variables starting with _ — "marcandre (Marc-Andre Lafortune)" <ruby-core@...>

15 messages 2012/07/04

[#46200] [ruby-trunk - Bug #6702][Open] Date should be either required or not — "rosenfeld (Rodrigo Rosenfeld Rosas)" <rr.rosas@...>

14 messages 2012/07/05

[#46296] [ruby-trunk - Feature #6717][Open] Method like #instance_eval that returns self (like #tap) — "alexeymuranov (Alexey Muranov)" <redmine@...>

10 messages 2012/07/10

[#46320] [ruby-trunk - Feature #6721][Open] Object#yield_self — "alexeymuranov (Alexey Muranov)" <redmine@...>

25 messages 2012/07/11

[#46339] [ruby-trunk - Bug #6724][Open] waaaaaaant! ( — "zenspider (Ryan Davis)" <redmine@...>

11 messages 2012/07/11

[#46377] [ruby-trunk - Feature #6727][Open] Add Array#rest (with implementation) — "duckinator (Nick Markwell)" <nick@...>

25 messages 2012/07/13

[#46492] [ruby-trunk - Feature #6737][Open] Add Hash#read and alias as #[]. — "trans (Thomas Sawyer)" <transfire@...>

12 messages 2012/07/15

[#46500] [ruby-trunk - Feature #6739][Open] One-line rescue statement should support specifying an exception class — Quintus (Marvin Gülker) <sutniuq@...>

22 messages 2012/07/15

[#46562] [ruby-trunk - Feature #6758][Open] Object#sequence — "merborne (kyo endo)" <redmine@...>

19 messages 2012/07/20

[#46574] [ruby-trunk - Feature #6762][Open] Control interrupt timing — "ko1 (Koichi Sasada)" <redmine@...>

39 messages 2012/07/20

[#46641] [ruby-trunk - Bug #6780][Open] cannot compile zlib module, when cross-compiling. — "jinleileiking (lei king)" <jinleileiking@...>

14 messages 2012/07/23

[#46659] [ruby-trunk - Bug #6783][Open] Infinite loop in inspect, not overriding inspect, to_s, and no known circular references. Stepping into inspect in debugger locks it up with 100% CPU. — "garysweaver (Gary Weaver)" <garysweaver@...>

8 messages 2012/07/23

[#46792] [ruby-trunk - Bug #6799][Open] Digest::*.hexdigest returns an ASCII-8BIT String — "Eregon (Benoit Daloze)" <redmine@...>

11 messages 2012/07/26

[#46799] [ruby-trunk - Feature #6801][Open] String#~ for a here document — "merborne (kyo endo)" <redmine@...>

12 messages 2012/07/27

[#46829] [ruby-trunk - Feature #6806][Open] Support functional programming: forbid instance/class variables for ModuleName::method_name, allow for ModuleName.method_name — "alexeymuranov (Alexey Muranov)" <redmine@...>

7 messages 2012/07/28

[#46832] [ruby-trunk - Bug #6807][Open] Can't compile ruby without ruby — "devcurmudgeon (Paul Sherwood)" <storitel@...>

13 messages 2012/07/28

[#46834] [ruby-trunk - Feature #6808][Open] Implicit index for enumerations — "trans (Thomas Sawyer)" <transfire@...>

15 messages 2012/07/28

[#46838] [ruby-trunk - Bug #6810][Open] `module A::B; end` is not equivalent to `module A; module B; end; end` with respect to constant lookup (scope) — "alexeymuranov (Alexey Muranov)" <redmine@...>

17 messages 2012/07/28

[#46896] (Half-baked DRAFT) new `require' framework — SASADA Koichi <ko1@...>

Hi,

22 messages 2012/07/31

[ruby-core:46407] [ruby-trunk - Bug #3589] Converting Bignums to Float for equality checks is wrong

From: "ko1 (Koichi Sasada)" <redmine@...>
Date: 2012-07-14 05:27:00 UTC
List: ruby-core #46407
Issue #3589 has been updated by ko1 (Koichi Sasada).

Description updated
Assignee changed from matz (Yukihiro Matsumoto) to akr (Akira Tanaka)
Target version set to 2.0.0


----------------------------------------
Bug #3589: Converting Bignums to Float for equality checks is wrong
https://bugs.ruby-lang.org/issues/3589#change-28026

Author: taw (Tomasz Wegrzanowski)
Status: Assigned
Priority: Normal
Assignee: akr (Akira Tanaka)
Category: core
Target version: 2.0.0
ruby -v: ruby 1.9.1p429 (2010-07-02 revision 28523) [i386-darwin9]


=begin
 In all versions of Ruby, when comparing Bignums with Floats, Bignum get converted to Floats first. This naturally results in wrong results, as this conversion is lossy. Not only will some unequal number be reported as equal, transitivity of equality gets broken:
 
 big    = 10**20
 bigger = big+1
 flt    = big.to_f 
 [big == bigger, big == flt, bigger == flt] #=> [false, true, true]
 
 Ruby is so close to getting equality right, it would be a shame not to get it totally right. And it's not Float's fault - IEEE 754 defines correct results of all Float operations to the last bit, and all rounding and comparisons between Floats happens with what is mathematically equivalent to infinite precision.
 
 = Solution 1 =
 
 Now I could be missing something, but it seems to be that it's all as simple as:
 * perform equality / comparison check like now with bignum.to_f and float
 * if they're not equal so far, direction of inequality is correct
 * compare bignum with float.to_i
 
 
 As both Float <=> Float, and Bignum <=> Bignum are exact to the last bit (ignoring issues like -0.0 etc. - they're not relevant here), this means roundtrip conversion is identity, and there can exist no other Float that would be equal to this particular Bignum, and no other Bignum that would be equal to this particular Float. It also seems to me that they'd need to be mathematically equal for that unless I miss something big.
 
 The first check ensures all fractional bits are correct (that is if flt has any it will fail as convertion of integer to float is guaranteed not to generate any). The second check ensures that all integer bits are correct (that is every bit exceeding limit of float representation is 0, as correct float to integer conversion is guaranteed not to geterate any there)
 
 This leads where we want:
 [bigger.to_f == flt, bigger == flt.to_i]
 => [true, false]
 
 
 Some pictures:
 * Huge BigNum XXXXXXXXXXXXXXXYYYYYYYYYYY.00000000000000
 * Huge Float  XXXXXXXXXXXXXXX00000000000.00000000000000
 * Small BigNum  XXXXXXX.000000000000000
 * Small Float   XXXXXXX.YYYYYYYYY000000
 
 0s are bits that cannot be represented, Xs bits represented by both, Ys bits represented in only one. Someone should double check with all the rounding etc. but it seems to that it's impossible for Ys to exist in both, if they're nearly equal.
 
 = Solution 2 =
 
 A completely different solution would be converting BigNum to Float with hardware (it's already universally supported, even if standard C tends to ignore it) in two modes - round up and round down (starting from low bits) - they will be the same or differ by 1ulp - so its impossible for the compared float to be between them. If bignum.to_f_up > flt, it's >. If bignum.to_f_down < flt, it's <. If they're all three equal, they're really ==.
=end



-- 
http://bugs.ruby-lang.org/

In This Thread

Prev Next