【发布时间】:2020-07-29 16:11:52
【问题描述】:
我有一个 C 代码,它以与人类相同的方式进行添加,因此,例如,如果我有两个数组 A[0..n-1] 和 B[0..n-1],则该方法将执行 C[0]=A[0]+B[0]、C[1]=A[1]+B[1].. .
即使解决方案使用内在函数,我也需要帮助来加快此功能。
我的主要问题是我有一个非常大的依赖性问题,因为迭代 i+1 取决于迭代 i 的进位,只要我使用基数 10。所以如果 A[0]=6 和 B[0]=5 , C[0] 必须是 1 并且我有一个 1 的进位用于下一次添加。
我能做的更快的代码是这个:
void LongNumAddition1(unsigned char *Vin1, unsigned char *Vin2,
unsigned char *Vout, unsigned N) {
for (int i = 0; i < N; i++) {
Vout[i] = Vin1[i] + Vin2[i];
}
unsigned char carry = 0;
for (int i = 0; i < N; i++) {
Vout[i] += carry;
carry = Vout[i] / 10;
Vout[i] = Vout[i] % 10;
}
}
但我也尝试了这些方法,结果速度较慢:
void LongNumAddition1(unsigned char *Vin1, unsigned char *Vin2,
unsigned char *Vout, unsigned N) {
unsigned char CARRY = 0;
for (int i = 0; i < N; i++) {
unsigned char R = Vin1[i] + Vin2[i] + CARRY;
Vout[i] = R % 10; CARRY = R / 10;
}
}
void LongNumAddition1(char *Vin1, char *Vin2, char *Vout, unsigned N) {
char CARRY = 0;
for (int i = 0; i < N; i++) {
char R = Vin1[i] + Vin2[i] + CARRY;
if (R <= 9) {
Vout[i] = R;
CARRY = 0;
} else {
Vout[i] = R - 10;
CARRY = 1;
}
}
}
我一直在谷歌研究,发现了一些与我实现的类似的伪代码,在 GeeksforGeeks 中也有另一个实现这个问题的方法,但速度也较慢。
你能帮帮我吗?
【问题讨论】:
-
除法(和模数)与加法(和减法)相比性能非常差。
if (a+b > 9) carry = 1; else carry = 0; -
可以肯定地提高性能的一点是使用数组中元素的更多值范围。目前,您使用 256 个可能值范围内的 10 个值。我建议您也使用不同的数据类型,例如
uint_fast32_t,因为这就是为什么您需要更少的 real 插件来进行添加。你可能想checkout它是如何在.net core中实现的 -
@JonathanSánchez 我说的是不将数字存储为基数为 10 的数字,而是存储为例如基数为 128 的数字,如果您想使用
uint_fast8_t或作为基数 - (2^ 16) 如果你想使用uint_fast32_t作为数组的元素类型。 -
您显然需要将您的以 10 为底的数字转换为以 128 为底的数字,但如果您对相同的数据进行多次加法,那至少应该加快速度跨度>
-
@JonathanSánchez 会更好,因为您必须减少 for 循环的迭代次数。这就是为什么在纸上对基数为 10 的数字进行加法比对二进制数进行手动加法更容易的原因
标签: c arrays performance optimization add