【问题标题】:Python Rounding Down to Custom StepPython四舍五入到自定义步骤
【发布时间】:2021-05-09 06:09:27
【问题描述】:

我们有一个部分工作的代码和 2 个包含不同类型自定义步骤的示例。示例 2 (Int) 有效,而示例 1 无效,因为它是向上取整而不是向下取整。

import math

def step_size_to_precision(ss):
    return ss.find('1') - 1

def format_value(val, step_size_str):
    precision = step_size_to_precision(step_size_str)
    if precision > 0:
        return "{:0.0{}f}".format(val, precision)
    return math.floor(int(val))


###########################

# # example 1
step_size = "0.00000100"
quantity = 0.00725562
print(quantity)
print(format_value(quantity, step_size))

# 0.00725562
# 0.007256  <= Is rounding up instead of down. Should be 0.007255 

###########################

# # example 2
# step_size = "1"
# quantity = 3.00725562
# print(quantity)
# print(format_value(quantity, step_size))

# returns 3 <= This is correct

###########################

我们如何解决它?

【问题讨论】:

    标签: python rounding


    【解决方案1】:

    您需要使用Decimal 对象来获取精确的十进制数字。

    然后,在ROUND_DOWN mode 中使用Decimal.quantize()

    from decimal import Decimal, ROUND_DOWN
    
    quantity = 0.00725562
    
    step_size = Decimal("0.000001")
    print(Decimal(quantity).quantize(step_size, ROUND_DOWN))
    

    打印出来

    0.007255
    

    【讨论】:

      【解决方案2】:

      this SO answer 中概述了另一种方法:

      如果你想向下舍入 总是(而不是四舍五入到最接近的 精度),然后明确地使用math.floor() function

      from math import floor
      
      def floored_percentage(val, digits):
          val *= 10 ** (digits + 2)
          return '{1:.{0}f}%'.format(digits, floor(val) / 10 ** digits)
      
      print floored_percentage(0.995, 1)
       Demo:
      
      >>> from math import floor
      >>> def floored_percentage(val, digits):
      ...     val *= 10 ** (digits + 2)
      ...     return '{1:.{0}f}%'.format(digits, floor(val) / 10 ** digits)
      ... 
      >>> floored_percentage(0.995, 1)
      '99.5%'
      >>> floored_percentage(0.995, 2)
      '99.50%'
      >>> floored_percentage(0.99987, 2)
      '99.98%'
      

      你的例子:

      import math
      
      def step_size_to_precision(ss):
          return max(ss.find('1'), 1) - 1
      
      def format_value(val, step_size):
          digits = step_size_to_precision(step_size)
          val *= 10 ** digits
          return '{1:.{0}f}'.format(digits, math.floor(val) / 10 ** digits)
      
      
      step_size = "0.00000100"
      quantity = 0.00725562
      print(quantity)
      print(format_value(quantity, step_size))
      
      # prints out: 0.007255
      

      【讨论】:

      • 问题是 step_size 是一个数字,而不是数字量。
      • 酷,现在它适用于示例 1,但示例 2 不起作用。我得到:ValueError:格式说明符缺少精度
      • 啊,是的,这主要是由于您的step_size_to_precision 功能。为了完整起见,我会修复它!
      • 我发现了一个异常,其中 AKX 答案不起作用(其中 stepsize = "1.0" 并且数量例如为 14.55。返回 14.5 而不是 14)另一方面,您的解决方案完美..非常感谢。
      【解决方案3】:

      一种更通用的方法,它允许对 step_size 进行舍入,这不仅仅是 10 的幂:

      from decimal import Decimal
      
      def floor_step_size(quantity, step_size):
          step_size_dec = Decimal(str(step_size))
          return float(int(Decimal(str(quantity)) / step_size_dec) * step_size_dec)
      

      用法:

      >>> floor_step_size(0.00725562, "0.00000100")
      0.007255
      >>> floor_step_size(3.00725562, "1")
      3.0
      >>> floor_step_size(2.6, "0.25")
      2.5
      >>> floor_step_size(0.9, "0.2")
      0.8
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-05
        • 2020-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-12
        • 2018-09-14
        相关资源
        最近更新 更多