查找小数位的简便方法

时间:2011-05-31 15:31:59

标签: python string decimal

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

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

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

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

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

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

非常感谢所有其他贡献。

9 个答案:

答案 0 :(得分:46)

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

对于decimal.Decimal对象,您可以使用as_tuple方法检索指数,该方法返回带有signdigits和{{1}的命名元组属性:

exponent

指数的否定是小数点后的位数,除非指数大于>>> d = decimal.Decimal('56.4325') >>> d.as_tuple().exponent -4 >>> d = decimal.Decimal('56.43256436') >>> d.as_tuple().exponent -8

答案 1 :(得分:10)

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

len(foo.split('.')[1])

其中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])

答案 2 :(得分:10)

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

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

尝试例如:

1.1 - int(1.1)

你会看到答案是:

0.10000000000000009

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

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

round(3.1415 - int(3.1415), 3)

对于这种情况,小数位数将减少为3。

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

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

答案 3 :(得分:4)

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

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

你最好的选择可能是在你的字符串中的点上分开并计算结果子字符串中的字符数。

答案 4 :(得分:1)

如果你知道你不会有解析问题(或者如果你让python本身或其他一些库为你处理,希望能处理本地化问题)...只需解析它并使用{{3} }。返回值是一对值,其中一个是不可分割的部分,另一个是小数部分。

答案 5 :(得分:1)

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

答案 6 :(得分:1)

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

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

由于浮点问题,即使使用十进制(数字),所有模数都会给我错误的结果(注意我在脚本中需要这个来修复整个数据库的价格)

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

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

这是我的“替补席”: https://repl.it/FM8m/17

答案 7 :(得分:1)

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

计算数字:

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

答案 8 :(得分:0)

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

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返回的指数最小。有效数字。

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