Ruby中一切皆对象,所以我不明白为什么我们需要Math模块。在我看来,Math模块中的大部分(全部?)函数应该是数字类型(如整数Integer、浮点数Float等)的方法。
例如,不应该是
Math.sqrt(5)
更合理的做法是:
5.sqrt
同样的情况也适用于sin,cos,tan,log10等函数。
有人知道为什么所有这些函数最终都在Math模块中吗?Ruby中一切皆对象,所以我不明白为什么我们需要Math模块。在我看来,Math模块中的大部分(全部?)函数应该是数字类型(如整数Integer、浮点数Float等)的方法。
例如,不应该是
Math.sqrt(5)
更合理的做法是:
5.sqrt
同样的情况也适用于sin,cos,tan,log10等函数。
有人知道为什么所有这些函数最终都在Math模块中吗?我不知道Ruby的早期历史,但是我有一种感觉,Math模块是基于C语言中的<math.h>头文件设计的。尽管如此,在Ruby标准库中它是一个奇怪的存在。
但是,这是Ruby!所以你总是可以使用monkey patching(猴子补丁)来解决问题!
class Float
def sqrt; Math.sqrt(self); end
def sin; Math.sin(self); end
def cos; Math.cos(self); end
def tan; Math.tan(self); end
def log10; Math.log10(self); end
end
进一步解释Michael的答案,没有必要手动定义所有这些方法。请注意,我明确跳过了需要两个参数的两个Math方法。
class Numeric
(Math.methods - Module.methods - ["hypot", "ldexp"]).each do |method|
define_method method do
Math.send method, self
end
end
end
puts 25.sqrt
puts 100.log10
输出:
5.0
2.0
关于为什么这些方法还未包含在Numeric
中,我真的不确定有一个好的理由。我认为像Andrew提到的那样的命名空间污染在Numeric
类中并不是特别危险的; Michael可能在历史传承方面是正确的。
define_method(method) do |*args| Math.send(method, self, *args) end
,不再需要排除 hypot
或 ldexp
。 - molfMath.methods(false).each {|m| define_method m do |*args| Math.send m, self, *args end }
- Camille Goudeseune我重新简化了Mark的答案,不需要删除hypot
和ldexp
,因为我自己也在使用这种方法。
class Numeric
Math.methods(false).each do |method|
define_method method do |*args|
Math.send(method, self, *args)
end
end
end
>> 3.hypot(4)
=> 5.0
>> Math::PI.sqrt
=> 1.7724538509055159
>> 10.log10
=> 1
sin
可能是一个模糊的术语。5 ** 0.5
表明Ruby的指数运算符可以直接处理平方根,而对于log、sin等函数,它们作为全局函数更有意义,而不是方法:它们的起源在于数学,与任何一个浮点实例都没有密切关联。