我被迫将输出存储在unsigned int
数组中。但是,输出是数组 modulo 2147483647中先前元素的线性组合的解,即 modulo 2 ^ 31-1。
以下是较大功能的代码段。很快,当ii
环绕xx
的索引时,此代码段会产生错误的答案。 (注意xx
在调用函数之前被播种,因此数组中的元素都不是空的。)
#include <stdint.h>
typedef unsigned int uint32;
typedef unit_least64_t uint64;
static uint32 xx[47];
...
xx[ii] = 12345 * (uint64)(xx[i0] + xx[ii]) % 2147483647; // i0, ii are defined elsewhere
但是,如果我们将最后一行与以下内容交换,我们将不断获得正确的解决方案。
xx[ii] = 12345 * ( (uint64)xx[i0] + (uint64)xx[ii] ) % 2147483647;
也许,很明显,但为什么有必要对unit64而不是一个进行两次类型转换呢?
答案 0 :(得分:1)
只要你把它放在正确的地方,一个类型的演员就足够了:
xx[ii] = 12345 * ( (uint64)xx[i0] + xx[ii] ) % 2147483647;
重要的是在添加之前进行转换以防止数字溢出,而不是在溢出已经发生之后。
答案 1 :(得分:1)
是的,您的初始代码可以这样写:
uint32 t1 = xx[i0] + xx[ii]; // problem is here, result of sum is truncated as it is 32 bit
uint64 t2 = (uint64)t1;
uint64 t3 = 12345 * t2 % 2147483647;
xx[ii] = (uint32)t3;
如果你使用第二种变体,你将拥有:
uint64 t0 = (uint64)xx[i0];
uint64 t1 = (uint64)xx[ii];
uint64 t2 = t0 + t1; // no truncation, as the result is 64 bit
uint64 t3 = 12345 * t2 % 2147483647;
xx[ii] = (uint32)t3;