【问题标题】:Easy way of finding decimal places查找小数位的简单方法
【发布时间】:2011-09-05 14:33:03
【问题描述】:

有没有一种简单的方法或集成函数来找出浮点数的小数位?

数字是从字符串中解析出来的,因此一种方法是计算“。”之后的数字。标志,但这对我来说看起来很笨拙。是否有可能从floatDecimal 对象中获取所需的信息?

解决方案(当然是其中之一:))

我选择使用 python decimal.Decimal 类来帮助我解决问题:

e = abs(Decimal(string_value).as_tuple().exponent)

注意:这仅适用于构造 Decimal 的参数是字符串而不是浮点数(这会导致浮点数不准确)。

非常感谢所有其他贡献。

【问题讨论】:

  • 在 python 中不确定,但在本地化时要非常小心,因为某些文化赋予“,”和“。”不同的含义。解释数字时的字符
  • 是的,你是对的,但就我而言,我可以确保以显示的数字格式获取值。但无论如何,谢谢你的信息。 :)
  • 您可能会落入旧的精度/准确性陷阱。简而言之,精度是点后面的位数。准确性是这些数字中有多少实际上是“正确的”。浮点表示是计算机仅逼近预期值的领域之一。
  • 如果你认为解决方案是从一个字符串值开始,为什么不直接从字符串中找到位数,而不是通过Decimal类型呢?
  • 正如我在问题中所说,我认为这种方法太笨拙了。并且它不符合没有小数位的数字或其他格式的数字(例如:科学)。 Decimal 类似乎是一个很好的抽象。

标签: python string decimal


【解决方案1】:

重复其他人所说的话(因为我已经打出来了!),由于十进制和二进制之间的差异,我什至不确定这样的值对于浮点数是否有意义表示;通常可以由有限个十进制数字表示的数字在二进制中只有无限位表示。

对于decimal.Decimal 对象,您可以使用as_tuple 方法检索指数,该方法返回具有signdigitsexponent 属性的命名元组:

>>> d = decimal.Decimal('56.4325')
>>> d.as_tuple().exponent
-4
>>> d = decimal.Decimal('56.43256436')
>>> d.as_tuple().exponent
-8

指数的取反是小数点后的位数,除非指数大于0

【讨论】:

  • 这与我的 Python(3.2 版)不同:decimal.Decimal(56.4325) 给出 Decimal('56.43249999999999744204615126363933086395263671875') 和 as_tuple().exponent 返回 -47
  • @Alexander,将其作为字符串尝试。 :)
  • @Alexander 试试 decimal.Decimal("56.4325")。您最初的尝试首先将 56.5425 转换为浮点数,然后转换为小数,这就是为什么您会得到如此接近 56.5425 且精度很高的小数。
  • @senderle 是的,好点。我确实错过了单引号。谢谢。
  • @BrianFisher,看到了这个并记住了我们的讨论——认为你可能想知道。 exponent确实有时会超过零:decimal.Decimal(500).normalize().as_tuple().exponent == 2
【解决方案2】:

“小数位数”不是浮点数具有的属性,因为它们在内部存储和处理的方式。

您可以从浮点数中获得任意多的小数位。问题是你想要多少准确度。将浮点数转换为字符串时,部分过程是决定准确性。

试一试:

1.1 - int(1.1)

你会看到答案是:

0.10000000000000009

因此,对于这种情况,小数位数为 17。这可能不是您要查找的数字。

但是,您可以使用“round”将数字四舍五入到一定的小数位数:

round(3.1415 - int(3.1415), 3)

在这种情况下,小数位数减少到 3。

您无法获得“浮点数的小数位数”,但您可以决定准确度和所需的位数。

将浮点数转换为字符串是做出此类决定的一种方式。

【讨论】:

  • 这是一篇出色的文章,因为它指出我的问题是错误的。但不幸的是,它对我的​​问题没有帮助。 (+1)
【解决方案3】:

十进制库用于处理十进制数,例如在会计中。它本身没有返回小数位数的功能。当您意识到它运行的上下文将其设置为用户想要的任何内容时,这尤其是一个问题。

如果您得到一个字符串,您可以将其转换为十进制,但这会添加零以确保您的准确性,或者使用舍入设置来截断它。

您最好的选择可能是拆分字符串中的点并计算结果子字符串中的字符数。

【讨论】:

    【解决方案4】:

    我找到的计算小数点后数字和四舍五入的最快方法是

    计算位数:

    a=decimal.Decimal('56.9554362669143476');
    lenstr = len(str(a).split(".")[1])
    

    计算、检查和四舍五入:

    a=decimal.Decimal('56.9554362669143476');
    a = round(float(a),5) if len(str(a).split(".")[1]) > 5 else float(a)
    

    比较:

    $ python2 -mtimeit 'import decimal; a=decimal.Decimal('56.9554362669143476'); round(float(a),5) if a.as_tuple().exponent < -5 else float(a)'
    10000 loops, best of 3: 32.4 usec per loop
    $ python -mtimeit 'import decimal; a=decimal.Decimal('56.9554362669143476'); a = round(float(a),5) if len(str(a).split(".")[1]) > 5 else float(a)'
    100000 loops, best of 3: 16.7 usec per loop
    

    【讨论】:

      【解决方案5】:

      如果您只需要找到最高有效数字的小数位,即。最左边的,另一种原始解决方案是:

      fraction = 0.001
      decimal_places = int(f'{fraction:e}'.split('e')[-1])
      

      这利用了科学记数法 (m x 10^n),它已经以 10 的幂 (n) 的形式提供了小数位数,系数 (m) 被提高到该值,即。 -3,从上述示例的 1.000000e-03 派生而来。

      Decimal(str(fraction)).as_tuple().exponent 的一个重要区别是,科学记数法始终只考虑指数 n 的最高有效数字,类似于Decimal().adjusted(),而Decimal().as_tuple().exponent 返回最低有效数字的指数。

      将字符串格式化为科学计数法当然也只能处理浮点数而不能处理字符串,因此任何浮点算术问题都会持续存在。但是,对于许多用例来说,以上可能就足够了。

      【讨论】:

        【解决方案6】:

        我需要这样的东西,我测试了其中一些,我发现最快的是:

        str(number)[::-1].find('.')
        

        由于浮点问题,即使使用 Decimal(number),所有模数都给了我错误的结果(请注意,我需要在脚本中使用它来修复整个数据库的价格)

        len(str(Decimal(str(number))) % Decimal(1))) - 2
        

        当我们有浮点数或类似的东西时,需要将一个字符串放入 Decimal 是非常令人不安的。

        这是我的“长凳”: https://repl.it/FM8m/17

        【讨论】:

          【解决方案7】:

          如果你知道你不会遇到解析问题(或者如果你让 python 本身或其他一些库为你处理,希望能处理本地化问题)......只需解析它并使用modf。返回值是一对值,一个是整数部分,一个是小数部分。

          【讨论】:

          • 这很有趣,但在我的情况下没有用,因为我仍然有 float 无法从中获取小数位数。
          【解决方案8】:

          由于 Python 浮点数在内部表示为二进制而不是十进制,因此除了转换为十进制之外,确实没有捷径可走。唯一的内置方法是转换为字符串。您可以编写自己的代码来进行十进制转换并计算数字,但这将是重复劳动。

          【讨论】:

            【解决方案9】:

            这对我有用:

            import decimal   
            
            def HowManyDecimals(decimal_number):
                    if not type(decimal_number) == "decimal.Decimal":
                        return "ERROR"
                    if not str(decimal_number).find(".") == -1:
                        decimals = len(str(decimal_number).split(".")[1])
                    else:
                        decimals = 0
                    return decimals
            
            a_decimal = decimal.Decimal("1.12345678901234567890123")
            print(HowManyDecimals(a_decimal))
            

            【讨论】:

              猜你喜欢
              • 2015-11-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多