我想出了以下方法来对数字求和。它似乎适用于大约 10^23 以下的数字,但不适用于更高的数字。为什么它不适用于更高的数字?
x=0
for i in range(0, 5000):
x+=((number/10**i)//1)%10
print(x)
撇开这是一种对数字求和的非常低效的方法,假设您使用的是 Python 3,print
请在循环中添加一个条件:
for i in range(0, 5000):
piece = ((number/10**i)//1)%10
if piece:
print(i, piece)
x+=((number/10**i)//1)%10
然后你就能看到哪里出了问题。从 开始number = 10**24
,我得到输出:
0 4.0
1 2.0
24 1.0
7.0
你不会期待那些中间结果,对吧?现在你只需要弄清楚你为什么得到它们;-)
短期课程是,当您应该进行整数计算时,您正在执行浮点计算。您立即下车(何时i
为 0):
>>> 10**24/10**0
1e+24
>>> _ // 1
1e+24
>>> _ % 10
4.0
这是为什么?因为10**24
不能完全表示为二进制浮点数:
>>> from decimal import Decimal
>>> Decimal(1e24)
Decimal('999999999999999983222784')
因此,为 存储的近似值的确切值1e24
是999999999999999983222784
,并且确实留下了4
除以 时的余数10
。
要解决这个问题,只需坚持整数运算:
number = 10**24
x=0
for i in range(0, 5000):
x += number//10**i % 10
print(x)
打印出来1
。更有效的是做,例如,
print(sum(int(ch) for ch in str(number)))
这并没有特别回答这个问题,但是每当您查看数字中的十进制数字时,您应该使用十进制模块:
from decimal import Decimal
sum(Decimal(number).as_tuple().digits)
与幼稚相比的一些优势sum(int(c) for c in str(int(abs(number))))
:
sum(int(c) for c in str(int(abs(1.32))))
#>>> 1
sum(Decimal(1.5).as_tuple().digits)
#>>> 6
注意
Decimal(1.3)
#>>> Decimal('1.3000000000000000444089209850062616169452667236328125')
因为1.3
是一个浮点数。你会想要
Decimal('1.3')
#>>> Decimal('1.3')
精确的小数。这可能会混淆您的浮点结果。
避免这种情况的一种方法是使用Decimal(str(number))
而不是Decimal(number)
,这会给你一个更明显但技术上不太正确的答案。
还:
%~> python -m timeit -s "from decimal import Decimal" -s "number = 123456789**10" "sum(int(c) for c in str(int(abs(number))))"
10000 loops, best of 3: 70.4 usec per loop
%~> python -m timeit -s "from decimal import Decimal" -s "number = 123456789**10" "sum(Decimal(number).as_tuple().digits)"
100000 loops, best of 3: 11.8 usec per loop
但真正的原因是它在概念上更简单,不考虑字符串而是考虑十进制表示。
这看起来像 Python 3。“//1”只是截断为整数值,如果您使用 // 进行第一次除法,则根本不需要它:
x=0
for i in range(0, 5000):
x += (number // 10**i)%10
print(x)
至于10^24,等于18,所以和是1+8=9。(^ 是 C 风格的按位异或整数参数。)
如果您想要 1 后面有 24 个零,请尝试 10**24。
关于你的循环边界。要获取数字整数部分的位数,请将“math”添加到您的导入中,然后:
ndigits = 1 + int(math.log10(max(1, abs(n))))
如果你知道你没有负数,你可以省略 abs()。如果您知道没有小于 1 的数字,则可以省略 max() 和 abs()。