【发布时间】:2021-09-06 09:56:14
【问题描述】:
Tl;dr:有没有办法以任何方式(包括多线程)改进下面的代码,因为代码将运行数千亿次?
目标是找到用于在伽罗瓦域 GF(4) 中执行乘法的恒定时间算法(没有 for 循环)。我不确定这是否可能,但值得一试。
一些背景:GF(2) 或以 2 为底的乘法相当于 anding 两个值相乘。这是因为:
| a | b | a × b = a ∧ b |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
例如:
10101011010100 × 10011000101101 =
10101011010100
10011000101101 ∧
--------------
10001000000100
当涉及到 GF(4) 时,可以使用四种不同的符号:0、1、2 和 3。它不与以 4 为底执行乘法相同,因为有些与其他数字相乘时,数字不会给出预期的结果。它们在下表中以粗体显示:
| a | b | a × b |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 2 | 0 |
| 0 | 3 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
| 1 | 2 | 2 |
| 1 | 3 | 3 |
| 2 | 0 | 0 |
| 2 | 1 | 2 |
| 2 | 2 | 3 |
| 2 | 3 | 1 |
| 3 | 0 | 0 |
| 3 | 1 | 3 |
| 3 | 2 | 1 |
| 3 | 3 | 2 |
上表更简洁的形式可以用下面的乘法表来概括:
| × | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 1 | 0 | 1 | 2 | 3 |
| 2 | 0 | 2 | 3 | 1 |
| 3 | 0 | 3 | 1 | 2 |
我们可以将四个数字中的每一个都写成二进制,因为乘法将在值的二进制表示上执行:
| Digit | Binary representation |
|---|---|
| 0 | 00 |
| 1 | 01 |
| 2 | 10 |
| 3 | 11 |
在 GF(4) 中,乘法是通过逐位相乘来完成的,没有进位。例如:
21302032 × 31012233 =
21302032
31012233 ×
--------
11003021
我们可以使用值的二进制表示并执行乘法:
21302032 = 1001110010001110 in binary
31012233 = 1101000110101111 in binary
11003021 = 0101000011001001 in binary
1001110010001110
1101000110101111 ×
----------------
0101000011001001
最后,这是一个执行乘法的工作 java 代码的实现。但是,它使用 for 循环,目标是提出恒定时间算法:
public class Multiplication {
public static void main(String[] args) {
final byte[][] MUL_ARRAY = new byte[][]{
{0, 0, 0, 0},
{0, 1, 2, 3},
{0, 2, 3, 1},
{0, 3, 1, 2}
};
long mask;
byte shift = 2;
//long is 64 bits which means it can store 32 digits quaternary value.
int n = 8; //# of quaternary digits (ALWAYS given)
long v1 = 0b1001110010001110;//21302012 in base 4
long v2 = 0b1101000110101111;//31012233 in base 4
long result = 0;
for (int i = 0; i < n; i++) {
//get far-right quaternary digit of the two vectors:
mask = 0b11;
mask = mask << 2 * (n - i - 1);
long v1DigitPadded = v1 & mask;//correct digit with zero padding
long v2DigitPadded = v2 & mask;//correct digit with zero padding
//shift the digits so that the digit needed is at far-right
v1DigitPadded = v1DigitPadded >>> 2 * (n - i - 1);
v2DigitPadded = v2DigitPadded >>> 2 * (n - i - 1);
//The actual quaternary digit
byte v1Digit = (byte) v1DigitPadded;
byte v2Digit = (byte) v2DigitPadded;
byte product = MUL_ARRAY[v1Digit][v2Digit];
long resultDigit = product << 2 * (n - i - 1);
result = result | resultDigit;
}
//desired output: 0101000011001001
//prints the value in binary with zeros padding on the left
String s = Long.toBinaryString(result);
String output = String.format("%" + n * 2 + "s", s).replace(" ", "0");
System.out.println("The output is: " + output);
}
}
有算法吗?如果没有,是否有一些改进可以帮助我的逻辑(可能是一种高效的多线程方法)?
【问题讨论】:
-
由于循环大小是恒定的,你的算法是恒定的时间...
标签: java algorithm optimization binary