【问题标题】:Limiting floats to two decimal points将浮点数限制为两位小数
【发布时间】:2023-01-08 21:09:47
【问题描述】:

我希望将 a 四舍五入为13.95.我尝试使用round,但我得到:

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

对于标准库 Decimal 类的类似问题,请参阅How can I format a decimal to always show 2 decimal places?

【问题讨论】:

  • 嗯……你是想代表货币吗?如果是这样,您不应该使用浮点数来换取美元。您可能会使用浮点数来表示便士,或者您尝试建模的最小通用货币单位恰好是什么,但最佳做法是使用十进制表示法,正如 HUAGHAGUAH 在他的回答中所建议的那样。
  • 重要的是不要用浮动表示货币。浮点数不精确。但是便士或美分的金额是整数。因此整数是表示货币的正确方式。
  • @Basic,这取决于(主要不是)。使用以美分或便士为单位的整数是傻瓜证明。它代表金钱的行业标准。如果您知道自己在做什么,对浮点运算和 Python 的 decimal 类有很好的理解,您可能会使用 decimal。但这在很大程度上取决于你的问题。你需要任意精度的小数吗?还是只有两位数?如果是两位数:整数。它让你远离麻烦。资料来源 我曾在一家银行软件咨询公司工作。
  • 我来晚了,但我想问一下,Python 的开发者解决了这个问题吗?因为当我做 round(13.949999999999999, 2) 时,我只得到 13.95。我已经在 Python 2.7.6 和 3.4 中试过了。有用。不确定 2.7 甚至在 2009 年是否存在。也许它是 Python 2.5 的东西?
  • @bad_keypoints:是的,舍入问题已由 Python 2.7.0+ 解决。更多my answer 这里

标签: python floating-point rounding precision


【解决方案1】:

您遇到了带有浮点数的 old problem,并非所有数字都可以准确表示。命令行只是向您显示内存中的完整浮点形式。

使用浮点表示,您的舍入版本是相同的数字。由于计算机是二进制的,它们将浮点数存储为整数,然后将其除以 2 的幂,因此 13.95 将以类似于 125650429603636838/(2**53) 的方式表示。

双精度数具有 53 位(16 位)的精度,而常规浮点数具有 24 位(8 位)的精度。 floating point type in Python uses double precision 用于存储值。

例如,

>>> 125650429603636838/(2**53)
13.949999999999999

>>> 234042163/(2**24)
13.949999988079071

>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999

如果您只在小数点后两位(例如显示货币值),那么您有几个更好的选择:

  1. 使用整数并以分而不是美元存储值,然后除以 100 以转换为美元。
  2. 或使用固定点数,如decimal

【讨论】:

  • @Christian 存储的价值与你如何存储价值之间存在根本区别展示那个值。格式化输出应该允许您根据需要添加填充,以及添加逗号分隔符等。
  • 值得一提的是"%.2f" % round(a,2)你不仅可以在printf中输入,还可以在str()之类的东西中输入
  • 为什么人们总是在浮点数舍入上假设货币?有时您只想降低精度。
  • @radtek:您需要了解二进制值(float 类型)只是十进制数(您作为人类所熟悉的)最接近的可用近似值。不存在 0.245 这样的(可有限表示的)二进制值。它根本不存在,并且在数学上不能存在。最接近 0.245 的二进制值略有少于0.245,自然向下舍入。同样,二进制中也没有0.225这样的东西,但最接近0.225的二进制值略有比...更棒0.225,自然会四舍五入。
  • @radtek:你确实要求解释。最直接的解决方案确实是使用Decimal,这是此答案中提供的解决方案之一。另一个是将您的数量转换为整数并使用整数运算。这两种方法也出现在其他答案和 cmets 中。
【解决方案2】:

有新的格式规范,String Format Specification Mini-Language

您可以执行以下操作:

"{:.2f}".format(13.949999999999999)

注一:以上返回一个字符串。为了获得浮动,只需用float(...)包裹:

float("{:.2f}".format(13.949999999999999))

笔记2:float() 包装不会改变任何东西:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True

【讨论】:

  • 要添加逗号,您也可以 '{0:,.2f}'.format(1333.949999999) 打印 '1,333.95'
  • @OnurYıldırım:是的,但您可以用float() 包装它; float("{0:.2f}".format(13.9499999))
  • @JossefHarush 你可以用 float() 包装它,但你没有得到任何东西。现在你又有了一个浮点数,同样不精确。 13.9499999999999 和 13.95 是相同的浮点数。
  • @NedBatchelder:我同意它们是相等的,但这将浮点数限制为两位小数:)
  • 顺便说一下,从 Python 3.6 开始我们可以使用 f-strings:f"Result is {result:.2f}"
【解决方案3】:

内置的 round() 在 Python 2.7 或更高版本中工作得很好。

例子:

>>> round(14.22222223, 2)
14.22

查看the documentation

【讨论】:

  • 那么我是否理解这是 Python 2.7 失败?为什么这样一个基本函数会产生从 v 2.7 到 v 3 的不同结果?
  • 但是round(2.16, 1)2.2为什么python只提供truncatefunc
  • 例如,如果您尝试将值 2.675 舍入到小数点后两位,您将得到此 >>> round(2.675, 2) 2.67 docs.python.org/2/tutorial/floatingpoint.html
  • 来自 Python 3 文档页面:Note The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
  • 请注意,如果您尝试使用此方法打印出诸如 1.00000 之类的数字,则无论您指定多少个小数点,它都只会打印出 1.0。
【解决方案4】:

让我举一个 Python 3.6 的 f-string/template-string 格式的例子,我认为它非常简洁:

>>> f'{a:.2f}'

它也适用于更长的示例,使用运算符并且不需要括号:

>>> print(f'Completed in {time.time() - start:.2f}s')

【讨论】:

    【解决方案5】:

    我觉得最简单的方法是使用format()函数。

    例如:

    a = 13.949999999999999
    format(a, '.2f')
    
    13.95
    

    这将生成一个浮点数作为四舍五入到两位小数的字符串。

    【讨论】:

      【解决方案6】:

      大多数数字不能用浮点数精确表示。如果你想四舍五入这个数字,因为这是你的数学公式或算法所需要的,那么你想使用四舍五入。如果您只是想将显示限制在一定的精度,那么甚至不要使用 round 并将其格式化为该字符串。 (如果你想用一些替代的舍入方法显示它,并且有吨,那么你需要混合这两种方法。)

      >>> "%.2f" % 3.14159
      '3.14'
      >>> "%.2f" % 13.9499999
      '13.95'
      

      最后,也许是最重要的,如果你想精确的数学那么你根本不需要花车。通常的例子是处理金钱并将“美分”存储为整数。

      【讨论】:

        【解决方案7】:

        使用

        print"{:.2f}".format(a)
        

        代替

        print"{0:.2f}".format(a)
        

        因为后者在尝试输出多个变量时可能会导致输出错误(参见cmets)。

        【讨论】:

        • 我的意思是,print"{0:.2f} {0:.2f}".format(a, b) 会导致输出错误 - 它会输出 'a' 值两次。而 print"{:.2f} {:.2f}".format(a, b) 将输出 'a' 和 'b' 值。
        • 对于 Python 3,您只需添加括号 print(...)。在他们里面,我写的一切都是正确的。
        • 如果你有两个变量,你会在 print("{0:.2f} {1:.2f}".format(a, b)) 之后
        【解决方案8】:

        试试下面的代码:

        >>> a = 0.99334
        >>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
        >>> print a
        0.99
        

        【讨论】:

        • 但请注意,a 的值仍然是一个不精确的浮点数。在这里查看 - repl.it/LJs(单击右侧部分顶部的“运行会话”)。
        • 如果您采用这种方法,您应该添加 0.5 以获得更准确的表示。整数(a * 100 + 0.5) / 100.0 ;使用 math.ceil 是另一种选择。
        • @ShashankSawant:好吧,一方面,所提供的答案不是四舍五入,而是截断了。在末尾添加一半的建议会四舍五入,但是与首先使用 round 函数相比,这样做没有任何好处。另一方面,因为这个解决方案仍然使用浮点数,所以 OP 的原始问题仍然存在,即使对于这个“解决方案”的“更正”版本也是如此。
        • -1,这只是round函数(在问题中使用过)的不必要的重新实现。
        • @interjay 如果 round() 不像 OP 提到的那样工作,那么这是必需的。
        【解决方案9】:

        TLDR ;)

        输入输出的舍入问题由 Python 3.1 最终解决并且修复程序也被反向移植到 Python 2.7.0。

        四舍五入的数字可以在 float 和 string 之间可逆地转换来回:
        str -> float() -> repr() -> float() ...Decimal -> float -> str -> Decimal

        >>> 0.3
        0.3
        >>> float(repr(0.3)) == 0.3
        True
        

        Decimal 类型不再需要存储。

        算术运算的结果必须再次四舍五入因为舍入错误可能会累积更多的不准确性,而不是解析一个数字后可能出现的情况。改进后的repr() 算法(Python >= 3.1,>= 2.7.0)没有解决这个问题:

        >>> 0.1 + 0.2
        0.30000000000000004
        >>> 0.1, 0.2, 0.3
        (0.1, 0.2, 0.3)
        

        输出字符串函数 str(float(...)) 在 Python < 2.7x 和 < 3.1 中四舍五入为 12 个有效数字,以防止类似于不固定的 repr() 输出的过多无效数字。在减去非常相似的数字后仍然不够,并且在其他操作后它过于四舍五入。 Python 2.7 和 3.1 使用相同长度的 str() 尽管 repr() 是固定的。一些旧版本的 Numpy 也有过多的无效数字,即使是固定的 Python。当前的 Numpy 是固定的。 Python 版本 >= 3.2 具有相同的 str() 和 repr() 函数结果以及 Numpy 中类似函数的输出。


        测试

        import random
        from decimal import Decimal
        for _ in range(1000000):
            x = random.random()
            assert x == float(repr(x)) == float(Decimal(repr(x)))  # Reversible repr()
            assert str(x) == repr(x)
            assert len(repr(round(x, 12))) <= 14         # no excessive decimal places.
        

        文档

        Release notes Python 2.7 - Other Language Changes第四段:

        转换现在浮点数和字符串之间正确四舍五入在大多数平台上。这些转换发生在许多不同的地方:浮点数和复数上的 str(); float 和 complex 构造函数;数字格式;使用marshalpicklejson模块对浮点数和复数进行序列化和反序列化;解析 Python 代码中的浮点数和虚数;和十进制到浮点数的转换。

        与此相关的是代表()浮点数 x 现在返回一个基于保证四舍五入到 x 的最短十进制字符串在正确的舍入下(使用四舍五入到四舍五入模式)。以前它给出了一个基于将 x 舍入为 17 位十进制数字的字符串。

        The related issue


        更多信息:Python 2.7 之前float 的格式类似于当前的numpy.float64。两种类型都使用相同的 64 位 IEEE 754 双精度和 52 位尾数。一个很大的区别是 np.float64.__repr__ 经常使用过多的十进制数字进行格式化,因此不会丢失任何位,但在 13.949999999999999 和 13.950000000000001 之间不存在有效的 IEEE 754 数字。结果不好,并且转换 repr(float(number_as_string)) 对于 numpy 是不可逆的。另一方面:float.__repr__ 的格式使得每个数字都很重要;序列没有间隙,转换是可逆的。很简单:如果您可能有一个 numpy.float64 数字,请将其转换为普通浮点数以便为人类格式化,而不是为数字处理器格式化,否则 Python 2.7+ 不需要更多。

        【讨论】:

        • 为什么投反对票?问题是关于 Python float(双精度)和普通 round,而不是关于 numpy.double 及其到字符串的转换。纯 Python 舍入确实不能比 Python 2.7 做得更好。大多数答案都是2.7之前写的,虽然本来很好,但已经过时了。这就是我回答的原因。
        • 包含“隐藏位”时为 53 位,隐式为 1,“逐渐下溢”期间除外。
        • 不是圆的错,是显示器的错。
        • 是的,这是众所周知的。但是,如果您反对 Python 2.7 发行说明或我的文本中的某些内容,或者根本不反对任何内容,我会想念上下文。这个问题的目的比必要的更复杂。应该补充的是,由于rounding bug on certain 32-bit Intel chips,从字符串到浮点数的转换也已在 Python 2.7 中得到修复,并且“round() 函数也是现在正确四舍五入。”(Release notes - 3.1 features backported to 2.7)。你能同意吗?
        • 糟糕,那是 a*bb*a。感谢您提供的链接——怀旧之情。
        【解决方案10】:

        使用:

        float_number = 12.234325335563
        round(float_number, 2)
        

        这将返回;

        12.23
        

        解释:

        圆形的函数有两个参数; 要四舍五入的数字和要返回的小数位数。这里我返回了两位小数。

        【讨论】:

        • 但是,如果我们说 0.093,您是如何获得额外的 0 的呢?这给我 0.1 作为答案
        • 如果您返回 2 位小数或通常比左侧小数部分中存在的零数多 1 位,那么您将获得所需的正确结果。例如,如果您仅将我的答案应用于数字 0.093,它会返回 0.09 但如果你只想得到 1 位小数,那么当然,它会返回 0.1 因为 0.0 是完全错误的。(我的代码以同样的方式工作。也许你只想得到 1 位小数。如果你想得到更准确的结果,你必须增加小数位数。)
        • 根据文档,它返回十进制是不正确的 ` 如果省略 ndigits 或 None,则返回值为整数。否则,返回值与数字具有相同的类型。 ndigits 可能是负数。`
        • 所有这些虚假的赞成票。您的回答只是重复十年前问问题时 OP 发布的代码。 OP 知道 round 函数。你根本没有解决他的问题。 (这个问题今天甚至不存在。)
        • 这不适用于更大的数字。 Round 的行为并不像人们想要的那样。我们想要十进制格式而不是圆形。 99.9999999987 不应该变成 100 它应该是 99.99。这是人们想要解决的问题。简单的小数学很容易。
        【解决方案11】:

        您可以修改输出格式:

        >>> a = 13.95
        >>> a
        13.949999999999999
        >>> print "%.2f" % a
        13.95
        

        【讨论】:

          【解决方案12】:

          对于 Python < 3(例如 2.6 或 2.7),有两种方法可以做到这一点。

          # Option one 
          older_method_string = "%.9f" % numvar
          
          # Option two (note ':' before the '.9f')
          newer_method_string = "{:.9f}".format(numvar)
          

          但请注意,对于高于 3 的 Python 版本(例如 3.2 或 3.3),选项二是 preferred

          有关选项二的更多信息,我建议使用string formatting from the Python documentation 上的此链接。

          有关选项一的更多信息,this link will suffice and has information on the various flags

          参考:Convert floating point number to a certain precision, and then copy to string

          【讨论】:

          • 你如何表示一个整数?如果我使用“{i3}”.format(numvar) 我得到一个错误。
          • 这就是我的意思:如果 numvar=12.456,则 "{:.2f}".format(numvar) 产生 12.46"{:2i}".format(numvar) 给出错误,我期待 12
          【解决方案13】:

          您可以使用 format 运算符在 Python 中将值四舍五入到小数点后两位:

          print(format(14.4499923, '.2f')) // The output is 14.45
          

          【讨论】:

          • 这返回字符串
          • 如果我们只是想截断,如何得到它。
          • 操作员?不是function吗?
          【解决方案14】:

          作为Matt pointed out,Python 3.6 提供了f-strings,他们也可以使用nested parameters

          value = 2.34558
          precision = 2
          width = 4
          
          print(f'result: {value:{width}.{precision}f}')
          

          这将显示result: 2.35

          【讨论】:

            【解决方案15】:

            在 Python 2.7 中:

            a = 13.949999999999999
            output = float("%0.2f"%a)
            print output
            

            【讨论】:

            • 这根本没有帮助。 output完全一样值为a,所以你最好在最后一行写print a而不是print output
            • @MarkDickinson 你能再试一次吗?因为它在我的编译器中按预期运行。
            • 你没有理解我的意思。是的,您的代码打印 13.95。但是 print a 也是如此,对于 a 的这个特定值,在 Python 2.7 中,所以不太清楚格式化步骤的意义是什么。
            • @MarkDickinson 我已经编辑了代码。我同意“打印 a”确实打印出与“打印输出”相同的值。但是,如果您比较“a==output”,结果将为“False”,因为格式化步骤会将浮点值“a”四舍五入为小数点后两位。
            • 您是否真的尝试使用a == output 来获取您显示的代码?它为我提供了 True,我怀疑它也为你提供了。
            【解决方案16】:

            我们有多种选择来做到这一点:

            选项1:

            x = 1.090675765757
            g = float("{:.2f}".format(x))
            print(g)
            

            选项 2: 内置的 round() 支持 Python 2.7 或更高版本。

            x = 1.090675765757
            g = round(x, 2)
            print(g)
            

            【讨论】:

            • 这个问题具体说了 round 方法没有做他想要的。查看this answer了解更多信息
            【解决方案17】:

            Python 教程有一个名为Floating Point Arithmetic: Issues and Limitations.阅读。它解释了正在发生的事情以及为什么 Python 正在竭尽全力。它甚至有一个与您的示例相匹配的示例。让我引用一点:

            >>> 0.1
            0.10000000000000001
            

            你可能想使用round() 功能将其切回单 你期望的数字。但这使得不 不同之处:

            >>> round(0.1, 1)
            0.10000000000000001
            

            问题是二进制 为“0.1”存储的浮点值 已经是最好的二进制文件 近似于1/10,所以试图 再次四舍五入不能让它变得更好: 它已经很好了。

            另一个结果是因为0.1 不完全是1/10,总结十 0.1 的值可能不会完全产生 1.0,要么:

            >>> sum = 0.0
            >>> for i in range(10):
            ...     sum += 0.1
            ...
            >>> sum
            0.99999999999999989
            

            您的问题的一种替代方法和解决方案是使用 decimal 模块。

            【讨论】:

              【解决方案18】:

              使用 Decimal 对象和 round() 方法的组合。

              Python 3.7.3
              >>> from decimal import Decimal
              >>> d1 = Decimal (13.949999999999999) # define a Decimal
              >>> d1 
              Decimal('13.949999999999999289457264239899814128875732421875')
              >>> d2 = round(d1, 2) # round to 2 decimals
              >>> d2
              Decimal('13.95')
              

              【讨论】:

              【解决方案19】:

              它完全按照您的指示进行操作并且工作正常。阅读更多关于 floating point confusion 的信息,也许可以试试 decimal 对象。

              【讨论】:

                【解决方案20】:
                from decimal import Decimal
                
                
                def round_float(v, ndigits=2, rt_str=False):
                    d = Decimal(v)
                    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
                    if rt_str:
                        return v_str
                    return Decimal(v_str)
                

                结果:

                Python 3.6.1 (default, Dec 11 2018, 17:41:10)
                >>> round_float(3.1415926)
                Decimal('3.14')
                >>> round_float(3.1445926)
                Decimal('3.14')
                >>> round_float(3.1455926)
                Decimal('3.15')
                >>> round_float(3.1455926, rt_str=True)
                '3.15'
                >>> str(round_float(3.1455926))
                '3.15'
                

                【讨论】:

                • 我们可以返回 float 而不是 Decimal 吗?喜欢:def round_float(v, ndigits=2) -&gt; float: d = Decimal(v); v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits)); return float(v_str)
                • @alper 你可以返回任何你喜欢的
                【解决方案21】:

                简单的解决方案在这里

                value = 5.34343
                rounded_value = round(value, 2) # 5.34
                

                【讨论】:

                • 这里有很多不必要的东西。 8/3 已经是 float 类型,所以 float 调用没有任何用处。直接调用 dunder 方法有点奇怪——相反,只需调用委托给那些 dunder 方法的函数。因此,拼写第一行的更好方法是简单地使用 value = round(8/3, 2)。那时你并没有真正添加其他答案中没有的任何内容。
                • 对不起,无关紧要的答案。我认为这是正确的方法。另外,在问题部分,他提到 round 方法不起作用,所以我没有检查它。
                【解决方案22】:

                使用这样的 lambda 函数:

                arred = lambda x,n : x*(10**n)//1/(10**n)
                

                这样你就可以这样做:

                arred(3.141591657, 2)
                

                并得到

                3.14
                

                【讨论】:

                • 什么是“武装”?是葡萄牙语吗?
                • @PeterMortensen 只是函数的名称,可以很容易地用def 编写。在这里创建一个lambda,真的是为了炫耀,没有什么特别的收获。
                • @PeterMortensen arred 是“arredondamento”的缩写,在葡萄牙语中是“四舍五入”
                • @Karl Knechtel 如果你使用'lambda',你会用更少的代码行得到相同的结果。这就是为什么我更喜欢使用它(只要可能)而不是'def'
                【解决方案23】:
                orig_float = 232569 / 16000.0
                

                14.5355625

                short_float = float("{:.2f}".format(orig_float)) 
                

                14.54

                【讨论】:

                  【解决方案24】:

                  为了修复 Python 和 JavaScript 等类型动态语言中的浮点数,我使用了这种技术

                  # For example:
                  a = 70000
                  b = 0.14
                  c = a * b
                  
                  print c # Prints 980.0000000002
                  # Try to fix
                  c = int(c * 10000)/100000
                  print c # Prints 980
                  

                  您还可以使用 Decimal,如下所示:

                  from decimal import *
                  getcontext().prec = 6
                  Decimal(1) / Decimal(7)
                  # Results in 6 precision -> Decimal('0.142857')
                  
                  getcontext().prec = 28
                  Decimal(1) / Decimal(7)
                  # Results in 28 precision -> Decimal('0.1428571428571428571428571429')
                  

                  【讨论】:

                  • getcontext().prec = 6 只适用于功能范围或所有地方?
                  • 上下文是算术运算的环境。它们控制精度,设置舍入规则,确定哪些信号被视为例外,并限制指数的范围。每个线程都有自己的当前上下文@JulioMarins
                  【解决方案25】:

                  很简单,就像:

                  1. 使用decimal模块进行快速正确舍入的十进制浮点运算:

                     d = Decimal(10000000.0000009)
                    

                    实现舍入:

                     d.quantize(Decimal('0.01'))
                    

                    结果为Decimal('10000000.00')

                  2. 制作以上DRY

                    def round_decimal(number, exponent='0.01'):
                        decimal_value = Decimal(number)
                        return decimal_value.quantize(Decimal(exponent))
                    

                    或者

                    def round_decimal(number, decimal_places=2):
                        decimal_value = Decimal(number)
                        return decimal_value.quantize(Decimal(10) ** -decimal_places)
                    

                    PS:批评别人:格式化不是四舍五入。

                  【讨论】:

                    【解决方案26】:

                    这是使用的简单解决方案format功能。

                    float(format(num, '.2f'))
                    

                    笔记:我们正在将数字转换为浮点数,因为格式化方法返回的是字符串。

                    【讨论】:

                      【解决方案27】:

                      如果你想处理钱,使用 Python decimal 模块:

                      from decimal import Decimal, ROUND_HALF_UP
                      
                      # 'amount' can be integer, string, tuple, float, or another Decimal object
                      def to_money(amount) -> Decimal:
                          money = Decimal(amount).quantize(Decimal('.00'), rounding=ROUND_HALF_UP)
                          return money
                      

                      【讨论】:

                      • 我试图将它与 DataFrame 的列一起使用。收到消息:TypeError:不支持从 Series 到 Decimal 的转换
                      【解决方案28】:
                      lambda x, n:int(x*10^n + 0.5)/10^n
                      

                      为我工作过许多多年使用多种语言。

                      【讨论】:

                      • 似乎连续两个“*”消失了。
                      【解决方案29】:

                      要将数字四舍五入为分辨率,最好的方法是以下方法,它适用于任何分辨率(两位小数或什至其他步长为 0.01):

                      >>> import numpy as np
                      >>> value = 13.949999999999999
                      >>> resolution = 0.01
                      >>> newValue = int(np.round(value/resolution))*resolution
                      >>> print newValue
                      13.95
                      
                      >>> resolution = 0.5
                      >>> newValue = int(np.round(value/resolution))*resolution
                      >>> print newValue
                      14.0
                      

                      【讨论】:

                      • 在 python 3.4.3 和 numpy 1.9.1 上对我不起作用? >>> 将 numpy 导入为 np >>> res = 0.01 >>> value = 0.184 >>> np.round(value/res) * res 0.17999999999999999
                      • 查找文档我发现问题来自numpy.round accuracy/precision。所以它需要在与分辨率相乘之前将其定义为int。我更新了代码。谢谢你!
                      • 唯一需要的是将 np.round 的numpy.float64结果转换为float或简单地使用round(value, 2)。 13.949999999999999 (= 1395 / 100.) 和 3.950000000000001 (= 1395 * .01) 之间不存在有效的 IEEE 754 编号。为什么你认为你的方法是最好的?原始值 13.949999999999999289 (= value = round(value, 2)) 甚至比您的 13.95000000000000178(由 np.float96 打印)更精确。 numpy 的更多信息现在已添加到 my answer,您可能错误地否决了它。最初与 numpy 无关。
                      • @hynekcer 我认为我的回答不是最好的。只是想将限制浮点数添加到 n 个小数但最接近定义的分辨率的示例。我按照你说的检查了,除了int你也可以使用float作为@szeitlin的例子。感谢您的额外评论。 (对不起,但我没有给你投反对票)
                      • 为数字处理(熊猫)添加全新的依赖项是“最佳方式”吗?
                      【解决方案30】:

                      我看到的答案不适用于 float(52.15) 案例。经过一些测试,我正在使用的解决方案是:

                      import decimal
                              
                      def value_to_decimal(value, decimal_places):
                          decimal.getcontext().rounding = decimal.ROUND_HALF_UP  # define rounding method
                          return decimal.Decimal(str(float(value))).quantize(decimal.Decimal('1e-{}'.format(decimal_places)))
                      

                      ('value' 转换为 float 和 string 非常重要,这样,'value' 可以是 float、decimal、integer 或 string 类型!)

                      希望这对任何人都有帮助。

                      【讨论】:

                        猜你喜欢
                        • 2018-03-04
                        • 1970-01-01
                        • 2021-04-23
                        • 1970-01-01
                        • 2022-01-11
                        • 1970-01-01
                        • 1970-01-01
                        • 2016-09-06
                        • 1970-01-01
                        相关资源
                        最近更新 更多