我正在将一个简单的随机数生成函数从C语言移植到Go语言,但结果不正确。

huangapple go评论115阅读模式
英文:

I am porting a simple RNG function from C to Go, gives incorrect result

问题

我正在将一个简单的随机数生成器从http://en.wikipedia.org/wiki/Multiply-with-carry移植到Golang。然而,我不知道哪里出错了,我的示例程序的结果是不一致的。

结果:

  1. C = 58 1 78 15 57 28 96 73 47 12 61 47 74 86 91 93
  2. 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代码:

  1. #include <cstdlib>
  2. #include <cstdio>
  3. #include <stdint.h>
  4. #define PHI 0x9e3779b9
  5. static uint32_t Q[4096], c = 362436;
  6. void init_rand(uint32_t x)
  7. {
  8. int i;
  9. Q[0] = x;
  10. Q[1] = x + PHI;
  11. Q[2] = x + PHI + PHI;
  12. for (i = 3; i < 4096; i++)
  13. Q[i] = Q[i - 3] ^ Q[i - 2] ^ PHI ^ i;
  14. }
  15. uint32_t rand_cmwc(void)
  16. {
  17. uint64_t t, a = 18782LL;
  18. static uint32_t i = 4095;
  19. uint32_t x, r = 0xfffffffe;
  20. i = (i + 1) & 4095;
  21. t = a * Q[i] + c;
  22. c = (t >> 32);
  23. x = t + c;
  24. if (x < c) {
  25. x++;
  26. c++;
  27. }
  28. return (Q[i] = r - x);
  29. }
  30. int main( int argc, char* argv[])
  31. {
  32. init_rand(0);
  33. uint32_t v=0;
  34. for( int i=0; i<16; i++)
  35. {
  36. v = rand_cmwc();
  37. printf("%d ", (v%100));
  38. }
  39. char input_buf[24]={0};
  40. printf("\nType a character to exit:", v);
  41. scanf("%s", input_buf);
  42. return 0;
  43. }
英文:

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:

  1. C = 58 1 78 15 57 28 96 73 47 12 61 47 74 86 91 93
  2. 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:

  1. #include &lt;cstdlib&gt;
  2. #include &lt;cstdio&gt;
  3. #include &lt;stdint.h&gt;
  4. #define PHI 0x9e3779b9
  5. static uint32_t Q[4096], c = 362436;
  6. void init_rand(uint32_t x)
  7. {
  8. int i;
  9. Q[0] = x;
  10. Q[1] = x + PHI;
  11. Q[2] = x + PHI + PHI;
  12. for (i = 3; i &lt; 4096; i++)
  13. Q[i] = Q[i - 3] ^ Q[i - 2] ^ PHI ^ i;
  14. }
  15. uint32_t rand_cmwc(void)
  16. {
  17. uint64_t t, a = 18782LL;
  18. static uint32_t i = 4095;
  19. uint32_t x, r = 0xfffffffe;
  20. i = (i + 1) &amp; 4095;
  21. t = a * Q[i] + c;
  22. c = (t &gt;&gt; 32);
  23. x = t + c;
  24. if (x &lt; c) {
  25. x++;
  26. c++;
  27. }
  28. return (Q[i] = r - x);
  29. }
  30. int main( int argc, char* argv[])
  31. {
  32. init_rand(0);
  33. uint32_t v=0;
  34. for( int i=0; i&lt;16; i++)
  35. {
  36. v = rand_cmwc();
  37. printf( &quot;%d &quot;, (v%100));
  38. }
  39. char input_buf[24]={0};
  40. printf( &quot;\nType a character to exit:&quot;, v);
  41. scanf(&quot;%s&quot;, input_buf);
  42. return 0;
  43. }

答案1

得分: 5

哦?

在更新时,C代码使用64位整数算术,并保留最高位的32位:

  1. i = (i + 1) & 4095;
  2. t = a * Q[i] + c;
  3. c = (t >> 32);

而在Go代码中,你只使用了32位整数;当然这是不正确的,因为它永远无法生成正确的高位。

英文:

Huh?

The C code does 64-bit integer arithemetic when updating, keeping the upper-most 32 bits:

  1. i = (i + 1) &amp; 4095;
  2. t = a * Q[i] + c;
  3. c = (t &gt;&gt; 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.

huangapple
  • 本文由 发表于 2013年8月22日 16:10:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/18374954.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定