【问题标题】:Ruby round float to_int if whole numberRuby round float to_int 如果是整数
【发布时间】:2010-11-07 19:41:12
【问题描述】:

在 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

【问题讨论】:

    标签: ruby floating-point int


    【解决方案1】:

    一种简单的方法是:

    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
    

    【讨论】:

    • 修改核心类有什么影响吗?
    【解决方案2】:

    单线冲刺...

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

    【讨论】:

    • 你会怎么做像"#{%g, percentage}% off"这样的事情?单线可以吗?
    • 不完全是,因为它不仅会下降.0,而且如果指数小于-4,它也会下降,并舍入它,例如:"%g" % 1.123456789 # => "1.12346"
    • Dennis,你可以这样做:"#{format('%g', percentage)}% off"formatsprintf 的别名,更可取)。
    【解决方案3】:

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

    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 输出到字符串的任何地方(例如,在表单中)都以我想要的方式出现它到(即,最后没有零)。

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

    【讨论】:

      【解决方案4】:

      我对 Ruby 了解不多。

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

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

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

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

      【讨论】:

      • 这是真的,但我希望它以这种方式显示 everywhere 浮点输出为字符串。基本上我想重写 Float.to_s 方法,或者把这个逻辑挂在它的末尾。
      • 在这种情况下你会如何使用增量?
      【解决方案5】:

      如果您使用的是 rails,您可以使用 helper number_to_rounded 和选项 strip_insignificant_zeros,例如:

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

      或者像这样:

      42.0.to_s(:rounded, strip_insignificant_zeros: true)
      

      【讨论】:

        【解决方案6】:

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

        (float == float.floor) ? float.to_i : float
        

        【讨论】:

          【解决方案7】:

          这是我为教育目的提供的骇人听闻的 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 方法更可靠。

          【讨论】:

            【解决方案8】:

            我对 Ruby 也不太了解。

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

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

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

            【讨论】:

              猜你喜欢
              • 2012-09-09
              • 2019-01-14
              • 1970-01-01
              • 2013-03-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-03-06
              • 2011-01-04
              相关资源
              最近更新 更多