为什么在Ruby中进行除法运算会返回整数而不是小数值?

308
例如:
9 / 5  #=> 1

但是我期望得到的是1.8。该怎么获得正确的小数(非整数)结果?为什么它返回了1


6
请注意,如果您实际上使用一种方法来返回此值,则不需要将其分配给变量;只需def method; a - b/8; end将从方法返回计算结果,因为在方法调用中的最后一个表达式是返回值。 - Phrogz
7个回答

407
它正在执行整数除法。您可以使用to_f将其强制转换为浮点模式:
9.to_f / 5  #=> 1.8
9 / 5.to_f  #=> 1.8

如果你的值是变量而不是文字,这个方法同样适用。将一个值转换为浮点数就足以将整个表达式强制转换为浮点算术。


2
这个答案比被接受的答案更符合“Rails”的风格。 - Sean Ryan
@muistooshort:抱歉,我无法复制它。可能是因为我做错了什么。 - Joao Costa
5
@SeanRyan 为什么特别选择Rails而不是一般的Ruby?我不明白为什么(Ruby on) Rails开发人员会在这种特定任务中与一般的Ruby开发人员有所不同。也许我只是在吹毛求疵,大多数人在这种情况下只是把(Ruby on)Rails和Ruby视为同义词。 - Chinoto Vokro
有没有一种方法可以确保在某个代码块中进行的所有数学计算都是使用浮点数(如果不是浮点数,则强制转换为浮点数),而无需对每个数值都进行 .to_f 转换? - stevec
1
@stevec 抱歉,我不知道有类似的东西。 - mu is too short
2
@stevec。我不知道这是否普遍适用,但在我使用过的所有块中,我只需要将其中一个值转换为浮点数。这似乎会将它与之交互的所有内容都转换为浮点数。 - Jeff Zivkovic

296

这是整数除法,您可以通过添加.0使其中一个数字成为Float类型:

9.0 / 5  #=> 1.8
9 / 5.0  #=> 1.8

11
这个方法有效,但下面的to_f答案似乎更有用。在Ruby中,to_f更符合惯用法吗? - notapatch
15
如果你正在除以包含整数的两个变量,例如 a.to_f / b,那么使用 .to_f 更好。如果你要除以硬编码的两个整数(这可能有点奇怪),则使用 9.0 / 5 就可以了。 - jefflunt
添加小数点将使其成为浮点数,当您进行除法运算时,它将把整数转换为浮点数,以便结果是浮点数。整数除法产生整数答案。在整数上使用 to_f 更加明确,而在整数后添加小数点 .0 更加隐含。我建议使用 to_f 更加明确,以便任何人阅读代码,尽管对于其他人来说仍然可能不清楚意图是什么。 - CTS_AE

194

2
这是我测试过的最快方法,唯一提高性能的方法是从一开始就将操作数分成浮点数。我用Ruby构建了一个质数生成器来学习语法,现在我正在优化它以了解哪种方法最有效。这是我准备的基准测试:require 'base64';require 'zlib';puts Zlib.inflate(Base64.decode64("eJxlkMEOwiAQRO98hekFuGzxQEwPXvwR01ZqiYHqBk2Tln8XDlWgnDbM25nJonq9NaoD7ZTtR9PigxK09zM7AkgRHieXTYHOsBNf1nklM6B6TuhYpdp+rPgSdiCOi/d/kQ71QBOtAVFLEDly05+UYQ2H+MckL6z0zioDdJG1S9K1K4iQAW66DhnmiqRYKEJFXMByux+XuOJ2XdO60dKsjC7aBtyTL5O5hLk=")) - Chinoto Vokro
一个问题,它是否会像我们使用“decimal”一样保留精度? - Adam Aiken
有没有办法获得整数结果,如果除法的被除数和除数都是整数,例如 17/2 = 8.5,16/2 = 8? - somenxavier

41

你可以在irb中进行检查:

$ irb
>> 2 / 3
=> 0
>> 2.to_f / 3
=> 0.666666666666667
>> 2 / 3.to_f
=> 0.666666666666667

26

您可以包含Ruby的 mathn 模块。

require 'mathn'

这样,您就能正常进行除法了。

1/2              #=> (1/2)
(1/2) ** 3       #=> (1/8)
1/3*3            #=> 1
Math.sin(1/2)    #=> 0.479425538604203

通过这种方式,您可以获得精确的除法(类Rational),直到您决定应用不能表示为有理数的操作,例如Math.sin


3
自 Ruby 2.2 起,mathn 模块已被弃用。 - Meier

11

5 改为 5.0,因为你正在进行整数除法。


7

这里没有提到Fixnum#to_r,它是自Ruby 1.9引入的。它将Fixnum转换成有理数形式。下面是它的用法示例。只要使用的所有数字都是Fixnum,它也可以提供精确的除法。

 a = 1.to_r  #=> (1/1) 
 a = 10.to_r #=> (10/1) 
 a = a / 3   #=> (10/3) 
 a = a * 3   #=> (10/1) 
 a.to_f      #=> 10.0

例子展示了在浮点数与有理数运算时,结果被转换为浮点数。

a = 5.to_r   #=> (5/1) 
a = a * 5.0  #=> 25.0 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接