rational - original numbers in ruby

半腔热情 提交于 2019-12-01 08:54:42

问题


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?


回答1:


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.




回答2:


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



回答3:


No, there is no such inbuilt private or public method that does what you want to do.

If you really want to store the original numbers inside the instance method, your monkey-patch is definitely one of the ways to do so.

In fact, the method Rational(a,b) is an instance method defined outside the class Rational, kind of like Array() and String() methods.



来源:https://stackoverflow.com/questions/20717858/rational-original-numbers-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!