![Excel で 32 ビット数を mod 2³² で乗算する](https://rvso.com/image/1520096/Excel%20%E3%81%A7%2032%20%E3%83%93%E3%83%83%E3%83%88%E6%95%B0%E3%82%92%20mod%202%C2%B3%C2%B2%20%E3%81%A7%E4%B9%97%E7%AE%97%E3%81%99%E3%82%8B.png)
Excel を使用して 32 ビットの整数を乗算し、下位 32 ビットを取得したいと考えています。つまり、数値 n1、n2 が与えられた場合、 を計算したいのですMOD(n1*n2, 2^32)
。ただし、この数式は Excel では機能しません。なぜなら、(n1 と n2 が大きい場合) 積が Excel の精度容量を超え、下位の桁が切り捨てられるからです。Excel を使用しながらこれを回避する方法はありますか?
私が思いついた原始的な解決策は、数字の 1 つを 8 ビットのチャンクに分割し、それに応じて乗算する (MOD
必要な場合は切り捨てる) というものでしたが、できればもっと簡単なものを探しています。
答え1
64ビットのOfficeを使用している場合は、カスタム関数を作成する新しいものを使用するLongLong
タイプ計算します。Alt+を押しF11てVisual Basic Editorを開き、挿入 > モジュール下のコードを貼り付けます
Public Function MulMod32(number1, number2) As Double
Dim n1 As LongLong, n2 As LongLong
n1 = CLngLng(number1)
n2 = CLngLng(number2)
' Sign-extend the numbers
n1 = IIf((n1 And &H80000000&) = 0, n1, n1 Or &HFFFFFFFF00000000^)
n2 = IIf((n2 And &H80000000&) = 0, n2, n2 Or &HFFFFFFFF00000000^)
MulMod32 = CDbl((n1 * n2) And &HFFFFFFFF^)
End Function
その後はMulMod32()
任意の式で使用できます。たとえば、=MulMod32(HEX2DEC("fffffffe"), HEX2DEC("ffff1234"))
ない場合はLongLong
、数値を小さな部分に分割して操作できますが、16ビットの値で十分なので、8ビットのチャンクで作業する必要はありません。aとbがある場合、それらを(ah、al)と(bh、bl)に分割した後、それらの積は次のように計算できます。
a × b = (ah × 2 16 + al)(bh × 2 16 + bl) = ah × bh × 2 32 + (ah × bl + al × bh) × 2 16 + al × bl
したがって、次の式を使用して、ah、al、bh、blの4つの列と積の列を作成できます。
A1 | B1 |
---|---|
ああ | =ビットシフト(a, 16) |
アル | =BITAND(a, 65535) |
bh | =ビットシフト(b, 16) |
bl | =ビットアンド(b, 65535) |
製品 | =BITAND(BITAND((ah*bl + bh*al), 65535)*2^16 + al*bl, 4294967295) |
答え2
見てみると仕様と制限少なくとも Excel 2007 以降では、次の制限が適用されていることがわかります。
特徴 上限 数値精度 15桁 許容される最小の負の数 -2.2251E-308 許容される最小の正の数 2.2251E-308 許容される最大の正の数 9.99999999999999E+307 許容される最大の負の数 -9.99999999999999E+307 式で許容される最大の正の数 1.7976931348623158e+308 数式で許容される最大の負の数 -1.7976931348623158e+308
ご覧のとおり、使用する数値によっては必然的に精度が低下します。
32 ビットの数値 (符号なし整数と仮定) を指定したため、計算する必要がある最大値は 18,446,744,073,709,551,616 (2 32 *2 32 = 2 64 ) となり、これは明らかに 15 桁の制限を超えていますが、計算できる最大数の制限は超えていません。
さらに、結果の下位 32 ビットを取得する予定の場合は、そのような計算を実行するために実際のプログラミング言語またはスクリプト言語に頼る方がよいでしょう。
答え3
私が思いついた原始的な解決策は、数字の 1 つを 8 ビットのチャンクに分割し、それに応じて乗算する (切り捨てが必要な場合は MOD を使用する) というものでしたが、できればもっと簡単なものを探しています。