1

我想出了以下方法来对数字求和。它似乎适用于大约 10^23 以下的数字,但不适用于更高的数字。为什么它不适用于更高的数字?

x=0
for i in range(0, 5000):
      x+=((number/10**i)//1)%10
print(x)
4

3 回答 3

3

撇开这是一种对数字求和的非常低效的方法,假设您使用的是 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')

因此,为 存储的近似值的确切值1e24999999999999999983222784,并且确实留下了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)))
于 2013-09-28T18:00:50.697 回答
3

这并没有特别回答这个问题,但是每当您查看数字中的十进制数字时,您应该使用十进制模块

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

但真正的原因是它在概念上更简单,不考虑字符串而是考虑十进制表示。

于 2013-09-28T18:21:33.457 回答
1

这看起来像 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()。

于 2013-09-28T17:58:47.877 回答