查找小数位的简便方法

Con*_*ius 46 python string decimal

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

该数字是从字符串中解析出来的,因此一种方法是计算'.'后面的数字.标志,但这对我来说看起来很笨拙.是否有可能从一个float或一个Decimal对象中获取所需的信息?

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

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

e = abs(Decimal(string_value).as_tuple().exponent)
Run Code Online (Sandbox Code Playgroud)

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

非常感谢所有其他贡献.

sen*_*rle 53

重复其他人所说的话(因为我已经输入了它!),我甚至不确定这个值在浮点数的情况下是否有意义,因为十进制和二进制表示之间的差异; 通常,由有限数量的十进制数字表示的数字将仅具有二进制的无限数字表示.

在的情况下,decimal.Decimal对象,你可以使用检索指数as_tuple方法,它返回一个namedtuple sign,digitsexponent属性:

>>> d = decimal.Decimal('56.4325')
>>> d.as_tuple().exponent
-4
>>> d = decimal.Decimal('56.43256436')
>>> d.as_tuple().exponent
-8
Run Code Online (Sandbox Code Playgroud)

除非指数大于,否则指数的否定是小数点后的位数0.

  • 这与我的Python(版本3.2)不同:decimal.Decimal(56.4325)给出Decimal('56 .43249999999999744204615126363933086395263671875')和as_tuple().exponent返回-47 (4认同)
  • @Alexander,试一试字符串.:) (4认同)
  • @Alexander尝试decimal.Decimal(“56.4325”)。您最初的尝试首先将 56.5425 转换为浮点数,然后转换为小数,这就是为什么您会得到如此接近 56.5425 且精度很高的小数。 (2认同)
  • @senderle 是的,好点。我确实错过了单引号。谢谢。 (2认同)

Mik*_*ton 12

一种天真的方式(易受@jglouie提到的本地化使用)是

len(foo.split('.')[1])
Run Code Online (Sandbox Code Playgroud)

其中foo是一个像"23.512999238"这样的字符串.

编辑

正如@Thomas Jung和@Mark Ransom所提到的,对于一些需要处理的角落情况来说这是相当幼稚的......

import re
from locale import localeconv
dec_pt = localeconv()['decimal_point']
decrgx = re.compile("\d+(%s\d+)?e(-|\+)(\d+)" % dec_pt)
if decrgx.search(foo):
    # still figuring this out
    raise NotImplementedError, "e notation not implemented"
else:
    digits = len(foo.split(dec_pt)[-1])
Run Code Online (Sandbox Code Playgroud)

  • 你需要处理`1.0001e + 110`以及`1e-110`.你应该拆分`locale.localeconv()['decimal_point']`而不是`'.'`来真正健壮. (2认同)

Ale*_*der 12

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

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

试试例如:

1.1 - int(1.1)
Run Code Online (Sandbox Code Playgroud)

你会看到答案是:

0.10000000000000009
Run Code Online (Sandbox Code Playgroud)

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

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

round(3.1415 - int(3.1415), 3)
Run Code Online (Sandbox Code Playgroud)

对于这种情况,小数位数减少到3.

你不能得到"浮点数的小数",但你可以决定准确度和你想要的数量.

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

  • 这是一篇很好的文章,因为它指出,我的问题是错误的.但不幸的是,它对我的​​问题没有帮助.(1) (2认同)

小智 8

我发现小数点后计算数字并对数字进行四舍五入的最快方法是

计算数字:

a=decimal.Decimal('56.9554362669143476');
lenstr = len(str(a).split(".")[1])
Run Code Online (Sandbox Code Playgroud)

计算、检查和四舍五入:

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

比较:

$ 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
Run Code Online (Sandbox Code Playgroud)


maw*_*all 8

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

fraction = 0.001
decimal_places = int(f'{fraction:e}'.split('e')[-1])
Run Code Online (Sandbox Code Playgroud)

这利用了科学记数法 (mx 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('.')
Run Code Online (Sandbox Code Playgroud)

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

len(str(Decimal(str(number))) % Decimal(1))) - 2
Run Code Online (Sandbox Code Playgroud)

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

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