Closed yoggy closed 8 years ago
Hi,
Sorry, I don't quite understand this. Why does the mathn library change the behaviour of the / operator? What is the different between / and .div?
It looks like mathn is part of the standard ruby build? Would it be possible to write a test that verifies this behaviour?
nick.
Hi njh,
I am interested in this strange behavior.
Do you know "Rational" class? Rational is defined when you require mathn.
Rational overrides Numeric#/ method. If Rational is defined, Fixnum#/ method returns a Rational number instead of a Fixnum.
$ irb
irb(main):001:0> 1000 / 123
=> 8
irb(main):002:0> (1000 / 123).class
=> Fixnum
irb(main):003:0> require 'mathn'
=> true
irb(main):004:0> 1000 / 123
=> (1000/123) #### Fixnum#/ returns Rational number!! ####
irb(main):005:0> (1000 / 123).class
=> Rational
Rational does not overide Numeric#div method. If you expect [Fixnum / Fixnum => Fixnum], you should use Fixnum#div method.
$ irb
irb(main):001:0> require 'mathn'
=> true
irb(main):002:0> 1000.div(128)
=> 7
irb(main):003:0> 1000.div(128).class
=> Fixnum
In this case, if require 'mathn'...
.
.
#### body_length is assumed to 11. ####
.
.
194 # Build up the body length field bytes
195 begin
196 digit = (body_length % 128)
197 body_length = (body_length / 128) #### (1) body_length is Rational number (11/128) [Fixnum / Fixnum => Rational] ####
198 # ....
199 digit |= 0x80 if (body_length > 0)
200 header.push(digit)
201 end while (body_length > 0)
194 # Build up the body length field bytes
195 begin
196 digit = (body_length % 128)
197 body_length = (body_length / 128)
198 # ....
199 digit |= 0x80 if (body_length > 0)
200 header.push(digit)
201 end while (body_length > 0) #### (2) Infinite loop generated, because body_length is not Zero!! ####
194 # Build up the body length field bytes
195 begin
196 digit = (body_length % 128) #### (3) digit changes to Rational [Rational % Fixnum => Rational] ####
197 body_length = (body_length / 128)
198 # ....
199 digit |= 0x80 if (body_length > 0)
200 header.push(digit)
201 end while (body_length > 0)
195 begin
196 digit = (body_length % 128)
197 body_length = (body_length / 128)
198 # ....
199 digit |= 0x80 if (body_length > 0) #### (4) NoMethodError occured. Rational#| method is not defined... ####
200 header.push(digit)
201 end while (body_length > 0)
Thanks for investigating yoggy.
So the key difference is that div will always return an integer - which is what we want because the remainder is being handled separately. We only what the whole number of divisions.
"Uses / to perform division, then converts the result to an integer."
It doesn't specifically say if the conversion uses floor(), ceil() or round() but I think it is fairly safe to assume floor.
Also still unsure how to write a test for this.
see also... https://gist.github.com/yoggy/aa77faba0a0840ef0faf2182d23a665c