29

在 ruby​​ 中,如果浮点数是整数,我想将其转换为 int。例如

a = 1.0
b = 2.5

a.to_int_if_whole # => 1
b.to_int_if_whole # => 2.5

基本上我试图避免在任何没有小数的数字上显示“.0”。我正在寻找一种优雅(或内置)的方式来做

def to_int_if_whole(float)
  (float % 1 == 0) ? float.to_i : float
end
4

8 回答 8

54

一种简单的方法是:

class Float
  def prettify
    to_i == self ? to_i : self
  end
end

那是因为:

irb> 1.0 == 1
=> true
irb> 1 == 1.0
=> true

然后你可以这样做:

irb> 1.0.prettify
=> 1

irb> 1.5.prettify
=> 1.5
于 2009-07-03T03:23:06.333 回答
50

单线冲刺...

sprintf("%g", 5.0)
=> "5"

sprintf("%g", 5.5)
=> "5.5"
于 2011-03-04T12:05:44.603 回答
5

这是最终以我想要的方式工作的解决方案:

class Float
  alias_method(:original_to_s, :to_s) unless method_defined?(:original_to_s)

  def is_whole?
    self % 1 == 0
  end

  def to_s
    self.is_whole? ? self.to_i.to_s : self.original_to_s
  end
end

这样我可以根据需要更新is_whole?逻辑(我似乎 tadman 是最复杂的),并且它确保 Float 输出到字符串的任何地方(例如,以一种形式)它以我想要的方式出现(即,不最后为零)。

感谢大家的想法——他们真的很有帮助。

于 2009-07-07T17:36:42.697 回答
3

我对Ruby了解不多。

但这是一个显示问题。如果您使用的库在将数字转换为字符串时无法格式化数字,我会感到非常惊讶。

可能没有一个包罗万象的格式化选项可以完全满足您的要求,但您可以设置一个方法,如果浮点数是整数的浮点表示,则返回 true,否则返回 false。在您创建的格式化例程中(因此您只需在一次地方执行此操作)只需根据这是真还是假来更改格式。

讨论了在显示数字时如何控制出现在小数点后的位数。

注意浮点表示的复杂性。数学可能会说答案是 3,但你可能会得到 3.000000000000000000001。我建议使用增量来查看数字是否几乎是整数。

于 2009-07-03T00:52:10.283 回答
3

如果您使用的是 rails,您可以使用number_to_rounded带有 option的 helper strip_insignificant_zeros,例如:

ActiveSupport::NumberHelper.number_to_rounded(42.0, strip_insignificant_zeros: true)

或像这样:

42.0.to_s(:rounded, strip_insignificant_zeros: true)
于 2015-04-13T10:03:05.017 回答
2

尽管我倾向于同意上述帖子,但如果您必须这样做:

(float == float.floor) ? float.to_i : float
于 2009-07-03T01:12:17.030 回答
1

这是我为教育目的提供的骇人听闻的 hacktastic 实现:

class Float
  def to_int_if_whole(precision = 2)
    ("%.#{precision}f" % self).split(/\./).last == '0' * precision and self.to_i or self
  end
end

puts 1.0.to_int_if_whole # => 1
puts 2.5.to_int_if_whole # => 2.5
puts 1.9999999999999999999923.to_int_if_whole # => 2

使用 sprintf 风格调用的原因是它处理浮点近似值比 Float#round 方法更可靠。

于 2009-07-03T19:32:12.570 回答
0

我对Ruby也不太了解。

但在 C++ 中,我会这样做:

bool IsWholeNumber( float f )
{
    const float delta = 0.0001;
    int i = (int) f;
    return (f - (float)i) < delta;
}

然后我会根据它来格式化输出精度。

于 2009-07-03T01:18:47.157 回答