2 進数の 1 桁を固定幅整数で合計するためのクールなトリックがあります。各反復で、数字の半分をそれぞれ 2 つの値に分け、1 つ下の値にビット シフトして加算します。最初の反復では、1 つおきの数字を分離します。2 回目の反復、数字のペアなど。
27 が 8 ビット バイナリとして 00011011 であることを考えると、プロセスは...
00010001 + 00000101 = 00010110 <- every other digit step
00010010 + 00000001 = 00010011 <- pairs of digits
00000011 + 00000001 = 00000100 <- quads, giving final result 4
10 進数でも同様のトリックを行うことができますが、選択した桁をゼロにして桁シフトを行う高速な操作で 10 進数を直接表現しない限り、単純なループよりも効率が悪くなります。したがって、12345678 の場合は...
02040608 + 01030507 = 03071115 <- every other digit
00070015 + 00030011 = 00100026 <- pairs
00000026 + 00000010 = 00000036 <- quads, final result
したがって、1+2+3+4+5+6+7+8 = 36 は正しいですが、数値表現が固定幅の 10 進数である場合にのみ、これを効率的に行うことができます。常に lg(n) 回の繰り返しが必要です。ここで、lg は 2 を底とする対数を意味し、切り上げます。
これを少し拡張するために(コメント内の議論に基づいて)、これが正気であるふりをしましょう...
1 桁の追加を数えると、実際には単純なループよりも多くの作業が必要になります。ビットをカウントするためのビット単位のトリックと同様に、(結合性を使用して) これらの加算の順序を変更し、1 つの全角加算を使用して 2 つの半角加算を実装し、4 つの加算を並列に計算するという考え方です。 4 分の 1 幅の追加など。数字のクリアと数字のシフト操作にはかなりのオーバーヘッドがあり、これをループとして実装するとさらに多くなります (各ステップの数字マスキングとシフト距離の値を計算または検索します)。「ループ」はおそらく完全に展開し、それらのマスクとシフト距離を定数としてコードに含めて、それを回避する必要があります。
Binary Coded Decimal (BCD)をサポートするプロセッサは、これを処理できます。数字のマスキングと数字のシフトは、ビットのマスキングとビットのシフトを使用して実装されます。これは、各 10 進数の数字が、他の数字のエンコードとは無関係に 4 (またはそれ以上) ビットでエンコードされるためです。
1 つの問題は、最近では BCD のサポートが非常にまれであることです。8 ビットと 16 ビットの時代にはかなり一般的でしたが、私の知る限り、現在もサポートしているプロセッサは主に下位互換性のためにサポートしています。理由は次のとおりです...
非常に初期のプロセッサには、ハードウェアの乗算と除算が含まれていませんでした。これらの演算のハードウェア サポートにより、2 進数から 10 進数への変換がより簡単かつ効率的になりました。バイナリは現在ほとんどすべてに使用されており、BCD はほとんど忘れられています。
ライブラリには 10 進数表現がありますが、ハードウェア BCD に移植可能なサポートを提供した高水準言語はほとんどありません。そのため、ほとんどの開発者にとってアセンブラーが現実世界のオプションではなくなったため、BCD サポートは使用されなくなりました。
数値が大きくなるにつれて、パックされた BCD でさえ非常に非効率的にパックされます。基数 10^x の数値表現は、基数 10 の最も重要な特性を持ち、10 進数として簡単にデコードされます。2^10 は 1024 であるため、基数 1000 は 3 桁あたり 12 ビットではなく 10 ビットしか必要としません。これで、32 ビットの 10 進数が 8 桁ではなく 9 桁になり、まだ 2 ビットが残っていることがわかります。 、たとえば符号ビットの場合。
問題は、この桁合計アルゴリズムがまったく価値があるためには、おそらく少なくとも 32 ビット (8 桁) の固定幅 10 進数で作業する必要があるということです。これにより、(完全に展開された) 単純なループの 15 の追加ではなく、12 の操作 (6 つのマスク、3 つのシフト、3 つの追加) が得られます。ただし、これは境界線上のゲインです。コード内の他の問題により、実際には遅くなる可能性があります。
64 ビット (16 桁の 10 進数) では、31 ではなく 16 の操作 (マスク 8、シフト 4、加算 4) しかないため、効率の向上は明らかですが、64 ビットの BCD 操作をサポートするプロセッサを見つける可能性は低いようです。たとえそうしたとしても、どのくらいの頻度でこれが必要ですか? 苦労して移植性を失う価値があるとは思えません。