【问题标题】:Rails rounding decimal to the nearest power of tenRails 将小数四舍五入到最接近的 10 次幂
【发布时间】:2018-03-09 07:14:51
【问题描述】:

我正在寻找一个可以将数字返回到最接近十的幂(10,100,1000)的rails函数,并且还需要支持0到1之间的数字(0.1、0.01、0.001):

round(9) = 10  
round(19) = 10  
round(79) = 100  
round(812.12) = 1000  

round(0.0321) = 0.01  
round(0.0921) = 0.1

我在看:Round number down to nearest power of ten
使用字符串长度接受的答案,不能应用于 0 到 1 之间的数字。

更新 Round up to nearest power of 10 这个看起来很棒。但我仍然无法让它在 Rails 中工作。

【问题讨论】:

    标签: ruby-on-rails numbers logic decimal rounding


    【解决方案1】:

    我不确定是否有任何函数可以自动将数字四舍五入到最接近的 10 次幂。您可以通过运行以下代码来实现它:

    def rounded_to_nearest_power_of_ten(value)
        abs_value = value.abs
        power_of_ten = Math.log10(abs_value)
        upper_limit = power_of_ten.ceil
        lower_limit = power_of_ten.floor
        nearest_value = (10**upper_limit - abs_value).abs > (10**lower_limit - abs_value).abs ? 10**lower_limit : 10**upper_limit
        value > 0 ? nearest_value : -1*nearest_value
    end
    

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      让我们将您的问题简化为以下形式 - 让输入数字在[0.1, 1) 范围内,那么这些数字的四舍五入会是什么样子?

      答案很简单 - 对于小于 0.5 的数字,我们将返回数字 0.1,对于更大的数字,它将返回 1.0

      我们所要做的就是确保我们的数字在这个范围内。我们将“移动”小数分隔符并记住我们在第二个变量中做了多少移动。此操作称为normalization

      def normalize(fraction)
          exponent = 0
      
          while fraction < (1.0/10.0)
              fraction *= 10.0
              exponent -= 1
          end
      
          while fraction >= 1.0
              fraction /= 10.0
              exponent += 1
          end
      
          [fraction, exponent]
      end
      

      使用上面的代码,您可以将任何浮点数表示为一对标准化分数和以 10 为底的指数。要重新创建原始数字,我们将使用公式将小数点沿相反方向移动

      原始 = 标准化 * 基数^{指数}

      通过规范化数据属性,我们可以在简单的舍入方法中使用它:

      def round(number)
          fraction, exponent = normalize(number)
      
          if fraction < 0.5
              0.1 * 10 ** exponent
          else
              1.0 * 10 ** exponent
          end
      end
      

      【讨论】:

        【解决方案3】:

        如果数字 >= 1.0,这应该可以工作。

        10 ** (num.floor.to_s.size - ( num.floor.to_s[0].to_i > 4 ? 0 : 1))
        

        【讨论】:

        【解决方案4】:

        试试这个:

        def round_tenth(a)
            if a.to_f >= 1
              return 10 ** (a.floor.to_s.size - ( a.floor.to_s[0].to_i > 4 ? 0 : 1))
            end
            #a = 0.0392
            c = a.to_s[2..a.to_s.length] 
            b = 0
            c.split('').each_with_index do |s, i|
              if s.to_i != 0
                b = i + 1
                break
              end
            end
            arr = Array.new(100, 0)
            if c[b-1].to_i > 4 
              b -= 1
              if b == 0
                return 1
              end
            end
            arr[b-1] = 1
            return ("0." + arr.join()).to_f
          end
        

        【讨论】:

        • 这完全符合我的需要!!是的,但你不可读。但这会有很大帮助!
        • 很高兴为您提供帮助。如果可能,标记为正确答案。谢谢
        【解决方案5】:
        class Numeric
          def name
            def helper x, y, z
              num = self.abs
              r = 1
              while true
                result = nil
                if num.between?(x, y)
                  if num >= y/2.0 
                    result = y.round(r+1) 
                  else
                    result = x.round(r)
                  end
                  return self.negative? ? -result : result
                end
                x *= z; y *= z; r += 1
              end
            end
        
            if self.abs < 1
              helper 0.1, 1, 0.1
            else 
              helper 1, 10, 10
            end
          end
        end
        

        例子

        -0.049.name # => -0.01
        12.name # => 10
        

        等等,不客气!

        【讨论】:

          猜你喜欢
          • 2011-05-22
          • 2011-03-21
          • 1970-01-01
          • 2021-08-01
          • 2017-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-28
          相关资源
          最近更新 更多