英文:
I am porting a simple RNG function from C to Go, gives incorrect result
问题
我正在将一个简单的随机数生成器从http://en.wikipedia.org/wiki/Multiply-with-carry移植到Golang。然而,我不知道哪里出错了,我的示例程序的结果是不一致的。
结果:
C = 58 1 78 15 57 28 96 73 47 12 61 47 74 86 91 93
GO= 58 8 18 48 90 72 18 84 54 52 94 80 18 8 2 0
我也不明白为什么原始源代码中的t和a使用uint64而不是uint32。
以下是C的主要部分和Go的计数器部分:
Go文件:http://play.golang.org/p/YVyIr1bcI8
原始C代码:
#include <cstdlib>
#include <cstdio>
#include <stdint.h>
#define PHI 0x9e3779b9
static uint32_t Q[4096], c = 362436;
void init_rand(uint32_t x)
{
int i;
Q[0] = x;
Q[1] = x + PHI;
Q[2] = x + PHI + PHI;
for (i = 3; i < 4096; i++)
Q[i] = Q[i - 3] ^ Q[i - 2] ^ PHI ^ i;
}
uint32_t rand_cmwc(void)
{
uint64_t t, a = 18782LL;
static uint32_t i = 4095;
uint32_t x, r = 0xfffffffe;
i = (i + 1) & 4095;
t = a * Q[i] + c;
c = (t >> 32);
x = t + c;
if (x < c) {
x++;
c++;
}
return (Q[i] = r - x);
}
int main( int argc, char* argv[])
{
init_rand(0);
uint32_t v=0;
for( int i=0; i<16; i++)
{
v = rand_cmwc();
printf("%d ", (v%100));
}
char input_buf[24]={0};
printf("\nType a character to exit:", v);
scanf("%s", input_buf);
return 0;
}
英文:
I am porting a simple RNG form http://en.wikipedia.org/wiki/Multiply-with-carry to Golang
However, don't know which part went wrong, the result of my sample program is inconsistent.
Result:
C = 58 1 78 15 57 28 96 73 47 12 61 47 74 86 91 93
GO= 58 8 18 48 90 72 18 84 54 52 94 80 18 8 2 0
And also I don't understand why t,a use uint64 instead of uint32 in the original source.
Below is C main and Go counter part:
Go file: http://play.golang.org/p/YVyIr1bcI8
Original C:
#include <cstdlib>
#include <cstdio>
#include <stdint.h>
#define PHI 0x9e3779b9
static uint32_t Q[4096], c = 362436;
void init_rand(uint32_t x)
{
int i;
Q[0] = x;
Q[1] = x + PHI;
Q[2] = x + PHI + PHI;
for (i = 3; i < 4096; i++)
Q[i] = Q[i - 3] ^ Q[i - 2] ^ PHI ^ i;
}
uint32_t rand_cmwc(void)
{
uint64_t t, a = 18782LL;
static uint32_t i = 4095;
uint32_t x, r = 0xfffffffe;
i = (i + 1) & 4095;
t = a * Q[i] + c;
c = (t >> 32);
x = t + c;
if (x < c) {
x++;
c++;
}
return (Q[i] = r - x);
}
int main( int argc, char* argv[])
{
init_rand(0);
uint32_t v=0;
for( int i=0; i<16; i++)
{
v = rand_cmwc();
printf( "%d ", (v%100));
}
char input_buf[24]={0};
printf( "\nType a character to exit:", v);
scanf("%s", input_buf);
return 0;
}
答案1
得分: 5
哦?
在更新时,C代码使用64位整数算术,并保留最高位的32位:
i = (i + 1) & 4095;
t = a * Q[i] + c;
c = (t >> 32);
而在Go代码中,你只使用了32位整数;当然这是不正确的,因为它永远无法生成正确的高位。
英文:
Huh?
The C code does 64-bit integer arithemetic when updating, keeping the upper-most 32 bits:
i = (i + 1) & 4095;
t = a * Q[i] + c;
c = (t >> 32);
In the Go code you use only 32-bit integers; of course that's not correct since it will never generate the proper upper bits.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论