Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rational - original numbers in ruby

How do I get the original numbers? For example when I type:

r = Rational(2, 10)
# (1/5)

2 and 10 will be changed to 1 and 5:

r.numerator   # 1
r.denominator # 5

How do I get 2 & 10 from instance of Rational class(r)?

I monkey-patched Rational class and created new method(Rational_o):

def Rational_o *args
  x, y = args
  r = Rational *args
  r.x = x
  r.y = y
  r
end

class Rational
  attr_accessor :x, :y
end

It works, but is there build-in method or variable(s) where original x & y are stored?

like image 375
Darek Nędza Avatar asked Jun 11 '26 08:06

Darek Nędza


2 Answers

No, there isn't. Reduction is a basic and common way to normalize rational numbers. Why would a rational number keep the original numerator and denominator? It does not make sense.

Your question is like asking "Does a string created by "foo" + "bar" (which becomes "foobar") keep the original substrings "foo" and "bar"? Where are they stored?"

If you really want to keep the original numbers, then a rational number is not what you want, and subclassing Rational is not the right way to go. You should use an array holding a pair of numbers.

like image 102
sawa Avatar answered Jun 17 '26 05:06

sawa


Rational numbers get normalized on initialization, so you can not know which numbers where given as original arguments. You can also not subclass Rational to install an initializer of your own, and monkeypatching as you do is not really the optimal way to achieve what you want to achieve (which I think you know).

What you can do is create a proxy around Rational with BasicObject which preserves the original arguments and will not disturb normal operation of the original Rational class

class RationalWithArgumentStore < BasicObject
  attr_accessor :original_arguments, :rational

  def initialize *args
    @original_arguments = args
    @rational = Rational *args
  end

  # Basic Object is a basic object, but defines ==
  # so let's overwrite it to route to rational
  def == other
    @rational == other
  end

  # Route all unknown method calls to rational
  def method_missing meth, *args, &block
    @rational.send meth, *args, &block
  end

end

def RationalWithArgumentStore(*args)
  RationalWithArgumentStore.new(*args)
end

So now you can do

my_rational = RationalWithArgumentStore(2,10)
my_rational.original_arguments #=> [2, 10]

#use it like a normal rational
my_rational * 3
my_rational.truncate
like image 43
Beat Richartz Avatar answered Jun 17 '26 05:06

Beat Richartz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!