Why BigDecial#fix return a BigDecimal instead of a Fixnum?

Hi!

According the docs,
http://www.ruby-doc.org/stdlib-2.1.5/libdoc/bigdecimal/rdoc/BigDecimal.html#method-i-fix,
Decimal#fix return the integer part of the number. I wonder why the object
returned by the fix method is an instance of BigDecimal instead of an
instance of Fixnum Similar problem happens with frac method.

a = BigDecimal(7)
=> #<BigDecimal:7fb18015e698,'0.7E1',9(27)>
a.fix
=> #<BigDecimal:7fb180185d38,'0.7E1',9(18)>
a.fix.to_i
=> 7

Thanks,

···

--
Juanjo Conti
Mi primer novela ya se puede conseguir en:
http://www.juanjoconti.com.ar/xolopes

Decimal#fix return the integer part of the number. I wonder why the object

returned by the fix method is an instance of BigDecimal instead of an
instance of Fixnum

Off the top of my pointy little head: probably because the value may be too
big for a Fixnum.

···

On Thursday, December 4, 2014, Juanjo Conti <jjconti@gmail.com> wrote:

--
Sent from Gmail Mobile; please excuse top posting, typos, etc. :frowning:

If that's what you want, try something like this:

irb2.1.5> require 'bigdecimal'
#2.1.5 => true
irb2.1.5> d = BigDecimal(7)
#2.1.5 => #<BigDecimal:7ffa1d88fee0,'0.7E1',9(27)>
irb2.1.5> d.fix
#2.1.5 => #<BigDecimal:7ffa1d88e130,'0.7E1',9(18)>
irb2.1.5> Integer(d.fix)
#2.1.5 => 7
irb2.1.5> Integer(d.fix).class
#2.1.5 => Fixnum

irb2.1.5> d = BigDecimal("3478654456787654567898765")
#2.1.5 => #<BigDecimal:7ffa1b8f9928,'0.3478654456 7876545678 98765E25',27(36)>
irb2.1.5> d.fix
#2.1.5 => #<BigDecimal:7ffa1d85f178,'0.3478654456 7876545678 98765E25',27(36)>
irb2.1.5> Integer(d.fix)
#2.1.5 => 3478654456787654567898765
irb2.1.5> Integer(d.fix).class
#2.1.5 => Bignum

-Rob

···

On 2014-Dec-4, at 10:16 , Dave Aronson <ruby-talk.list.2.TRex@Codosaur.us> wrote:

On Thursday, December 4, 2014, Juanjo Conti <jjconti@gmail.com> wrote:

Decimal#fix return the integer part of the number. I wonder why the object returned by the fix method is an instance of BigDecimal instead of an instance of Fixnum

Off the top of my pointy little head: probably because the value may be too big for a Fixnum.

So, fix should return Fixnum or Bignum, not Decimal. I'm tempted to report
it as a bug. Don't you agree?

···

2014-12-04 12:30 GMT-03:00 Rob Biedenharn <rob.biedenharn@gmail.com>:

On 2014-Dec-4, at 10:16 , Dave Aronson <ruby-talk.list.2.TRex@Codosaur.us> > wrote:

On Thursday, December 4, 2014, Juanjo Conti <jjconti@gmail.com> wrote:

Decimal#fix return the integer part of the number. I wonder why the

object returned by the fix method is an instance of BigDecimal instead of
an instance of Fixnum

Off the top of my pointy little head: probably because the value may be
too big for a Fixnum.

If that's what you want, try something like this:

irb2.1.5> require 'bigdecimal'
#2.1.5 => true
irb2.1.5> d = BigDecimal(7)
#2.1.5 => #<BigDecimal:7ffa1d88fee0,'0.7E1',9(27)>
irb2.1.5> d.fix
#2.1.5 => #<BigDecimal:7ffa1d88e130,'0.7E1',9(18)>
irb2.1.5> Integer(d.fix)
#2.1.5 => 7
irb2.1.5> Integer(d.fix).class
#2.1.5 => Fixnum

irb2.1.5> d = BigDecimal("3478654456787654567898765")
#2.1.5 => #<BigDecimal:7ffa1b8f9928,'0.3478654456 7876545678
98765E25',27(36)>
irb2.1.5> d.fix
#2.1.5 => #<BigDecimal:7ffa1d85f178,'0.3478654456 7876545678
98765E25',27(36)>
irb2.1.5> Integer(d.fix)
#2.1.5 => 3478654456787654567898765
irb2.1.5> Integer(d.fix).class
#2.1.5 => Bignum

-Rob

--
Juanjo Conti
Mi primer novela ya se puede conseguir en:

Just glanced at the tests in ruby, this is all I found
(test/bigdecimal/test_bigdecimal.rb).

Doesn't provide much clarification.

def test_fix
  x = BigDecimal.new("1.1")
  assert_equal(1, x.fix)
end

···

On Thu, Dec 4, 2014 at 9:44 AM, Rob Biedenharn <rob.biedenharn@gmail.com> wrote:

On 2014-Dec-4, at 10:37 , Juanjo Conti <jjconti@gmail.com> wrote:

So, fix should return Fixnum or Bignum, not Decimal. I'm tempted to report
it as a bug. Don't you agree?

No, I don't agree. Integer and Decimal are both Numeric, but I think that
it's less surprising for #fix and #frac to both return the same
type—BigDecimal. It would be completely surprising if BigDecimal("7").frac
returned a Fixnum 0 even though there is no fractional part of 7. (And, of
course, BigDecimal("7").frac.zero? is true)

-Rob

2014-12-04 12:30 GMT-03:00 Rob Biedenharn <rob.biedenharn@gmail.com>:

On 2014-Dec-4, at 10:16 , Dave Aronson <ruby-talk.list.2.TRex@Codosaur.us> >> wrote:

On Thursday, December 4, 2014, Juanjo Conti <jjconti@gmail.com> wrote:

Decimal#fix return the integer part of the number. I wonder why the

object returned by the fix method is an instance of BigDecimal instead of
an instance of Fixnum

Off the top of my pointy little head: probably because the value may be
too big for a Fixnum.

If that's what you want, try something like this:

irb2.1.5> require 'bigdecimal'
#2.1.5 => true
irb2.1.5> d = BigDecimal(7)
#2.1.5 => #<BigDecimal:7ffa1d88fee0,'0.7E1',9(27)>
irb2.1.5> d.fix
#2.1.5 => #<BigDecimal:7ffa1d88e130,'0.7E1',9(18)>
irb2.1.5> Integer(d.fix)
#2.1.5 => 7
irb2.1.5> Integer(d.fix).class
#2.1.5 => Fixnum

irb2.1.5> d = BigDecimal("3478654456787654567898765")
#2.1.5 => #<BigDecimal:7ffa1b8f9928,'0.3478654456 7876545678
98765E25',27(36)>
irb2.1.5> d.fix
#2.1.5 => #<BigDecimal:7ffa1d85f178,'0.3478654456 7876545678
98765E25',27(36)>
irb2.1.5> Integer(d.fix)
#2.1.5 => 3478654456787654567898765
irb2.1.5> Integer(d.fix).class
#2.1.5 => Bignum

-Rob

--
Juanjo Conti
Mi primer novela ya se puede conseguir en:
http://www.juanjoconti.com.ar/xolopes

--

<http://www.kapowevents.com/?utm_campaign=signature&utm_medium=email&utm_source=office&utm_content=kapow-events&gt;
SAAD REHMANI | CTO
*O*: 312-374-4101 *|* *C*: 469-774-6267
KapowEvents.com
<http://www.kapowevents.com/?utm_campaign=signature&utm_medium=email&utm_source=office&utm_content=kapow-events&gt;
Corporate events made easy.

So, fix should return Fixnum or Bignum, not Decimal. I'm tempted to report it as a bug. Don't you agree?

No, I don't agree. Integer and Decimal are both Numeric, but I think that it's less surprising for #fix and #frac to both return the same type—BigDecimal. It would be completely surprising if BigDecimal("7").frac returned a Fixnum 0 even though there is no fractional part of 7. (And, of course, BigDecimal("7").frac.zero? is true)

-Rob

···

On 2014-Dec-4, at 10:37 , Juanjo Conti <jjconti@gmail.com> wrote:

2014-12-04 12:30 GMT-03:00 Rob Biedenharn <rob.biedenharn@gmail.com>:

On 2014-Dec-4, at 10:16 , Dave Aronson <ruby-talk.list.2.TRex@Codosaur.us> wrote:

On Thursday, December 4, 2014, Juanjo Conti <jjconti@gmail.com> wrote:

Decimal#fix return the integer part of the number. I wonder why the object returned by the fix method is an instance of BigDecimal instead of an instance of Fixnum

Off the top of my pointy little head: probably because the value may be too big for a Fixnum.

If that's what you want, try something like this:

irb2.1.5> require 'bigdecimal'
#2.1.5 => true
irb2.1.5> d = BigDecimal(7)
#2.1.5 => #<BigDecimal:7ffa1d88fee0,'0.7E1',9(27)>
irb2.1.5> d.fix
#2.1.5 => #<BigDecimal:7ffa1d88e130,'0.7E1',9(18)>
irb2.1.5> Integer(d.fix)
#2.1.5 => 7
irb2.1.5> Integer(d.fix).class
#2.1.5 => Fixnum

irb2.1.5> d = BigDecimal("3478654456787654567898765")
#2.1.5 => #<BigDecimal:7ffa1b8f9928,'0.3478654456 7876545678 98765E25',27(36)>
irb2.1.5> d.fix
#2.1.5 => #<BigDecimal:7ffa1d85f178,'0.3478654456 7876545678 98765E25',27(36)>
irb2.1.5> Integer(d.fix)
#2.1.5 => 3478654456787654567898765
irb2.1.5> Integer(d.fix).class
#2.1.5 => Bignum

-Rob

--
Juanjo Conti
Mi primer novela ya se puede conseguir en: http://www.juanjoconti.com.ar/xolopes

I don’t agree. BigDecimal#fix returns a BigDecimal because it’s convenient; the documentation doesn’t make any guarantees about type, and the code doesn’t do any particular conversions:

In most cases, I don’t find myself caring about the class of the result, just that the result responds as expected to further usage. BigDecimal(7) works enough like Integer(7) that I don’t need to get picky about the type.

If you’re having issues with how the number is displayed to the user, look into using the `sprintf` method on Kernel, which gives you much more control.

···

On Dec 4, 2014, at 10:37, Juanjo Conti <jjconti@gmail.com> wrote:

So, fix should return Fixnum or Bignum, not Decimal. I'm tempted to report it as a bug. Don't you agree?

Yup, you're probably right. Thanks.

···

2014-12-04 13:00 GMT-03:00 Bryce Kerley <bkerley@brycekerley.net>:

On Dec 4, 2014, at 10:37, Juanjo Conti <jjconti@gmail.com> wrote:

So, fix should return Fixnum or Bignum, not Decimal. I'm tempted to report
it as a bug. Don't you agree?

I don’t agree. BigDecimal#fix returns a BigDecimal because it’s
convenient; the documentation doesn’t make any guarantees about type, and
the code doesn’t do any particular conversions:

ruby/ext/bigdecimal/bigdecimal.c at bc0f131277af6b6cd65a5e75c3b8a2d9d8b073ad · ruby/ruby · GitHub

jruby/core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java at e86c673ba2c3c1e776382b0588fd08cea4109fae · jruby/jruby · GitHub

In most cases, I don’t find myself caring about the class of the result,
just that the result responds as expected to further usage. BigDecimal(7)
works enough like Integer(7) that I don’t need to get picky about the type.

If you’re having issues with how the number is displayed to the user, look
into using the `sprintf` method on Kernel, which gives you much more
control.

--
Juanjo Conti
Mi primer novela ya se puede conseguir en:

Python works the same way:

decimal.Decimal(7).imag

Decimal('0')

decimal.Decimal(7).real

Decimal('7')

···

2014-12-04 13:08 GMT-03:00 Juanjo Conti <jjconti@gmail.com>:

Yup, you're probably right. Thanks.

2014-12-04 13:00 GMT-03:00 Bryce Kerley <bkerley@brycekerley.net>:

On Dec 4, 2014, at 10:37, Juanjo Conti <jjconti@gmail.com> wrote:

So, fix should return Fixnum or Bignum, not Decimal. I'm tempted to
report it as a bug. Don't you agree?

I don’t agree. BigDecimal#fix returns a BigDecimal because it’s
convenient; the documentation doesn’t make any guarantees about type, and
the code doesn’t do any particular conversions:

ruby/ext/bigdecimal/bigdecimal.c at bc0f131277af6b6cd65a5e75c3b8a2d9d8b073ad · ruby/ruby · GitHub

jruby/core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java at e86c673ba2c3c1e776382b0588fd08cea4109fae · jruby/jruby · GitHub

In most cases, I don’t find myself caring about the class of the result,
just that the result responds as expected to further usage. BigDecimal(7)
works enough like Integer(7) that I don’t need to get picky about the type.

If you’re having issues with how the number is displayed to the user,
look into using the `sprintf` method on Kernel, which gives you much more
control.

--
Juanjo Conti
Mi primer novela ya se puede conseguir en:
http://www.juanjoconti.com.ar/xolopes

--
Juanjo Conti
Mi primer novela ya se puede conseguir en:

To avoid ambiguity it might be helpful if the documentation for
BigDecimal#fix said that it returned the integer part of the value as
a BigDecimal.

This behaviour could be useful if you want to convert something to an
"integer value", and then want to be able to divide into that "integer
value" without the result being truncated to an integer.

If you really need an Integer then BigDecimal#to_i and
BigDecimal#floor seem to work.

To avoid ambiguity it might be helpful if the documentation for
BigDecimal#fix said that it returned the integer part of the value as
a BigDecimal.

Generally math operations return the most appropriate type. For
example from a Fixnum multiplication you can get back a Fixnum or a
Bignum. You really should not be caring about the type too much, I
think. Note that even printf will happily output a BigDecimal as
integer value.

This behaviour could be useful if you want to convert something to an
"integer value", and then want to be able to divide into that "integer
value" without the result being truncated to an integer.

It is also useful to avoid unnecessary conversions. By returning
BigDecimal method #fix probably does less work. If a conversion to
Fixnum or Bignum was integrated then the user could never get a
BigDecimal out of #fix and it may have to be recreated during a
#coerce call done in another math operation. So that would mean a lot
unnecessary work.

If you really need an Integer then BigDecimal#to_i and
BigDecimal#floor seem to work.

I'd rather use #to_int than #to_i because that is the proper method
which enforces integerness.

If you are interested in how numeric classes usually work in Ruby I
have blogged about this a looong time ago:
http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html

Kind regards

robert

···

On Thu, Dec 4, 2014 at 10:13 PM, Colin Bartlett <colinb2r@googlemail.com> wrote:

--
[guy, jim].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/

I submitted a patch today that clarifies the docs accordingly.

(See https://bugs.ruby-lang.org/issues/10576\)

Best regards,
Marcus

···

Am 04.12.2014 um 22:13 schrieb Colin Bartlett:

To avoid ambiguity it might be helpful if the documentation for
BigDecimal#fix said that it returned the integer part of the value as
a BigDecimal.

--
GitHub: https://github.com/stomar/
PGP: 0x6B3A101A

Sorry for my delay in responding.

Yes, I agree about #to_int. I should have paid closer attention to
your blog when I read it when it first came out!

I also managed not to notice the text in later editions of Programming
Ruby on the difference between unstrict and strict conversion
functions. (In my "defence", when I learned Ruby in the early 2000s
from the first (hard copy) edition of "Programming Ruby", there wasn't
a Fixnum#to_int. At least, it isn't documented in the online version
Programming Ruby: The Pragmatic Programmer's Guide although String#to_str *is*
and I didn't take the reason for that and #to_s onboard at the time.)

Just to reinforce the distinction in my mind, these make a similar point.

http://www.rubyfleebie.com/to_i-vs-to_int/

http://globaldev.co.uk/2013/09/ruby-tips-part-2/

"Why are there two methods, to_i and to_int, in BigDecimal when they
are exactly same in terms of functionality. ..."

Updated by Nobuyoshi Nakada over 2 years ago:
They are not specific to BigDecimal.
to_i is for explicit conversion, called by users.
to_int is for implicit conversion, called by core/libraries.

https://forums.pragprog.com/forums/54/topics/992
I don’t understand what’s the difference between to_s and to_str (the
same for to_i - to_int, to_a - to_ary, and so), and why we need both
method styles.

Dave Thomas's reply: The short forms (to_s, to_i, etc) say “do your
best to give me a string/integer/… representation of the receiver).
The to_str longer-form methods say instead that the receiver can
effectively be viewed as a string, and ask for the string
representation. So the short forms are permissive, and the long forms
will give an error if no exact conversion exists.

Now I might remember and use the distinction!

···

On Thu, Dec 4, 2014 at 10:13 PM, Colin Bartlett <colinb2r@googlemail.com> wrote:

...
If you really need an Integer then BigDecimal#to_i and
BigDecimal#floor seem to work.

On 12/5/14, Robert Klemme <shortcutter@googlemail.com> wrote:

...
I'd rather use #to_int than #to_i because that is the proper method
which enforces integerness.

If you are interested in how numeric classes usually work in Ruby I
have blogged about this a looong time ago:
http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html