From: akr@... Date: 2016-05-03T09:10:39+00:00 Subject: [ruby-core:75321] [Ruby trunk Bug#12337] inconsistency between Fixnum#coerce and Bignum#coerce Issue #12337 has been updated by Akira Tanaka. File int-coerce.patch added I made a patch to fix this problem. This implements bignum.coerce(float) to be [float, float] and fixnum.coerce(bignum) to be [bignum, bignum]. ``` % ./ruby -e ' fixnum = 3 bignum = 2**70 float = 5.0 [fixnum, bignum, float].each {|n1| [fixnum, bignum, float].each {|n2| result = n1.coerce(n2).map {|n| n.class } rescue $!.class puts "#{n1.class}.coerce(#{n2.class}) => #{result.inspect}" } }' Fixnum.coerce(Fixnum) => [Fixnum, Fixnum] Fixnum.coerce(Bignum) => [Bignum, Bignum] Fixnum.coerce(Float) => [Float, Float] Bignum.coerce(Fixnum) => [Bignum, Bignum] Bignum.coerce(Bignum) => [Bignum, Bignum] Bignum.coerce(Float) => [Float, Float] Float.coerce(Fixnum) => [Float, Float] Float.coerce(Bignum) => [Float, Float] Float.coerce(Float) => [Float, Float] ``` Note that a released version works as follows. ``` % ruby-2.3.1 -e ' fixnum = 3 bignum = 2**70 float = 5.0 [fixnum, bignum, float].each {|n1| [fixnum, bignum, float].each {|n2| result = n1.coerce(n2).map {|n| n.class } rescue $!.class puts "#{n1.class}.coerce(#{n2.class}) => #{result.inspect}" } }' Fixnum.coerce(Fixnum) => [Fixnum, Fixnum] Fixnum.coerce(Bignum) => [Float, Float] Fixnum.coerce(Float) => [Float, Float] Bignum.coerce(Fixnum) => [Bignum, Bignum] Bignum.coerce(Bignum) => [Bignum, Bignum] Bignum.coerce(Float) => TypeError Float.coerce(Fixnum) => [Float, Float] Float.coerce(Bignum) => [Float, Float] Float.coerce(Float) => [Float, Float] ``` ---------------------------------------- Bug #12337: inconsistency between Fixnum#coerce and Bignum#coerce https://bugs.ruby-lang.org/issues/12337#change-58449 * Author: Akira Tanaka * Status: Open * Priority: Normal * Assignee: * ruby -v: ruby 2.4.0dev (2016-05-01 trunk 54866) [x86_64-linux] * Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN ---------------------------------------- I found 1.coerce(2.0) is [2.0, 1.0] but (2**100).coerce(2.0) raises TypeError ``` % ./ruby -ve 'p 1.coerce(2.0)' ruby 2.4.0dev (2016-05-01 trunk 54866) [x86_64-linux] [2.0, 1.0] % ./ruby -ve 'p (2**100).coerce(2.0)' ruby 2.4.0dev (2016-05-01 trunk 54866) [x86_64-linux] -e:1:in `coerce': can't coerce Float to Bignum (TypeError) from -e:1:in `
' ``` This is a documented behavior. ``` % ri Bignum.coerce|cat = Bignum.coerce (from ruby core) ------------------------------------------------------------------------------ big.coerce(numeric) -> array ------------------------------------------------------------------------------ Returns an array with both a numeric and a big represented as Bignum objects. This is achieved by converting numeric to a Bignum. A TypeError is raised if the numeric is not a Fixnum or Bignum type. (0x3FFFFFFFFFFFFFFF+1).coerce(42) #=> [42, 4611686018427387904] ``` But I think this is bad bahavior. Fixnum and Bignum should work seamlessly. For example, this exposes the platform is 32-bit or 64-bit. 2**40 is Fixnum on 32-bit environment and Bignum on 64-bit environment. So, (2**40).coerce(2.0) behaves differently: returns an array on 64-bit and raises TypeError on 32-bit platform. ``` 32bit-platform% ./ruby -ve 'p (2**40).coerce(2.0)' ruby 2.4.0dev (2016-05-01 trunk 54866) [x86_64-linux] [2.0, 1099511627776.0] 64bit-platform% ./ruby -ve 'p (2**40).coerce(2.0)' ruby 2.4.0dev (2016-05-01 trunk 54864) [i686-linux] -e:1:in `coerce': can't coerce Float to Bignum (TypeError) from -e:1:in `
' ``` I think the behavior of Bignum#coerce should be changed to match Fixnum#coerce (actually defined at Numeric). ---Files-------------------------------- int-coerce.patch (2.37 KB) -- https://bugs.ruby-lang.org/ Unsubscribe: