桁数を合計する次の方法を思いつきました。約 10^23 未満の数値では機能するようですが、それ以上の数値では機能しません。数値が大きいとうまくいかないのはなぜですか?
x=0
for i in range(0, 5000):
x+=((number/10**i)//1)%10
print(x)
これは特に質問に答えるものではありませんが、数値の10進数を見ているときはいつでもdecimalモジュールを使用する必要があります:
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
しかし、本当の理由は、文字列ではなく 10 進表現について考える方が概念的に単純だからです。
これは数字を合計する非常に非効率的な方法であることはさておき、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
2 進浮動小数点数として正確に表現できないため:
>>> 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)))
これは 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() を省略できます。