未初始化的局部变量是最快的随机数发生器吗?

本文翻译自:Is uninitialized local variable the fastest random number generator?

I know the uninitialized local variable is undefined behaviour( UB ), and also the value may have trap representations which may affect further operation, but sometimes I want to use the random number only for visual representation and will not further use them in other part of program, for example, set something with random color in a visual effect, for example: 我知道未初始化的局部变量是未定义的行为( UB ),并且该值可能具有可能影响进一步操作的陷阱表示,但有时我想仅使用随机数进行可视化表示,并且不会在其他部分使用它们。例如,程序在视觉效果中设置具有随机颜色的东西,例如:

void updateEffect(){
    for(int i=0;i<1000;i++){
        int r;
        int g;
        int b;
        star[i].setColor(r%255,g%255,b%255);
        bool isVisible;
        star[i].setVisible(isVisible);
    }
}

is it that faster than 是不是比它快

void updateEffect(){
    for(int i=0;i<1000;i++){
        star[i].setColor(rand()%255,rand()%255,rand()%255);
        star[i].setVisible(rand()%2==0?true:false);
    }
}

and also faster than other random number generator? 并且还比其他随机数发生器更快?


#1楼

参考:https://stackoom.com/question/29Ay8/未初始化的局部变量是最快的随机数发生器吗


#2楼

No, it's terrible. 不,这太可怕了。

The behaviour of using an uninitialised variable is undefined in both C and C++, and it's very unlikely that such a scheme would have desirable statistical properties. 使用未初始化变量的行为在C和C ++中都是未定义的,并且这种方案不太可能具有理想的统计属性。

If you want a "quick and dirty" random number generator, then rand() is your best bet. 如果你想要一个“快速而肮脏”的随机数生成器,那么rand()是你最好的选择。 In its implementation, all it does is a multiplication, an addition, and a modulus. 在其实现中,它所做的只是乘法,加法和模数。

The fastest generator I know of requires you to use a uint32_t as the type of the pseudo-random variable I , and use 我所知道的最快的生成器要求你使用uint32_t作为伪随机变量I的类型,并使用

I = 1664525 * I + 1013904223

to generate successive values. 生成连续的值。 You can choose any initial value of I (called the seed ) that takes your fancy. 您可以选择任何您喜欢的I初始值(称为种子 )。 Obviously you can code that inline. 显然你可以编写内联代码。 The standard-guaranteed wraparound of an unsigned type acts as the modulus. 无符号类型的标准保证环绕充当模数。 (The numeric constants are hand-picked by that remarkable scientific programmer Donald Knuth.) (数字常数由杰出的科学程序员Donald Knuth亲自挑选。)


#3楼

Undefined behavior means that the authors of compilers are free to ignore the problem because programmers will never have a right to complain whatever happens. 未定义的行为意味着编译器的作者可以自由地忽略这个问题,因为程序员永远无权抱怨发生的任何事情。

While in theory when entering UB land anything can happen (including a daemon flying off your nose ) what normally means is that compiler authors just won't care and, for local variables, the value will be whatever is in the stack memory at that point. 虽然从理论上讲,当进入UB土地时, 任何事情都可能发生 (包括从你的鼻子飞出守护进程 )通常意味着编译器作者根本不会关心,对于局部变量,该值将是此时堆栈内存中的任何内容。

This also means that often the content will be "strange" but fixed or slightly random or variable but with a clear evident pattern (eg increasing values at each iteration). 这也意味着内容通常是“奇怪的”但是固定的或稍微随机的或可变的但具有明显的明显模式(例如,在每次迭代时增加值)。

For sure you cannot expect it being a decent random generator. 当然,你不能指望它是一个像样的随机发电机。


#4楼

Good question! 好问题!

Undefined does not mean it's random. 未定义并不意味着它是随机的。 Think about it, the values you'd get in global uninitialized variables were left there by the system or your/other applications running. 想一想,您在全局未初始化变量中获得的值是由系统或您/其他应用程序运行的。 Depending what your system does with no longer used memory and/or what kind of values the system and applications generate, you may get: 根据系统对不再使用的内存和/或系统和应用程序生成的值的不同,您可能会得到:

  1. Always the same. 总是一样。
  2. Be one of a small set of values. 是一小组价值观之一。
  3. Get values in one or more small ranges. 获取一个或多个小范围内的值。
  4. See many values dividable by 2/4/8 from pointers on 16/32/64-bit system 从16/32/64位系统上的指针中查看2/4/8可分割的许多值
  5. ... ...

The values you'll get completely depend on which non-random values are left by the system and/or applications. 您将获得的值完全取决于系统和/或应用程序留下的非随机值。 So, indeed there will be some noise (unless your system wipes no longer used memory), but the value pool from which you'll draw will by no means be random. 所以,确实会有一些噪音(除非你的系统不再使用内存),但你所绘制的价值池绝不是随机的。

Things get much worse for local variables because these come directly from the stack of your own program. 局部变量的情况变得更糟,因为它们直接来自您自己程序的堆栈。 There is a very good chance that your program will actually write these stack locations during the execution of other code. 您的程序很可能在执行其他代码期间实际编写这些堆栈位置。 I estimate the chances for luck in this situation very low, and a 'random' code change you make tries this luck. 我估计在这种情况下运气的可能性非常低,你做的“随机”代码改变试试这个运气。

Read about randomness . 阅读随机性 As you'll see randomness is a very specific and hard to obtain property. 正如您将看到的随机性是一个非常具体且难以获得的属性。 It's a common mistake to think that if you just take something that's hard to track (like your suggestion) you'll get a random value. 这是一个常见的错误,认为如果你只是采取一些难以追踪的东西(比如你的建议),你会得到一个随机值。


#5楼

Because of security reasons, new memory assigned to a program has to be cleaned, otherwise the information could be used, and passwords could leak from one application into another. 由于安全原因,必须清理分配给程序的新内存,否则可能会使用信息,并且密码可能会从一个应用程序泄漏到另一个应用程序。 Only when you reuse memory, you get different values than 0. And it is very likely, that on a stack the previous value is just fixed, because the previous use of that memory is fixed. 只有当你重用内存时,才会得到不同于0的值。而且很有可能,在堆栈中,之前的值只是固定的,因为之前使用的内存是固定的。


#6楼

As others have noted, this is Undefined Behavior (UB). 正如其他人所说,这是未定义的行为(UB)。

In practice, it will (probably) actually (kindof) work. 在实践中,它(可能)实际上(有点)工作。 Reading from an uninitialized register on x86[-64] architectures will indeed produce garbage results, and probably won't do anything bad (as opposed to eg Itanium, where registers can be flagged as invalid , so that reads propagate errors like NaN). 从x86 [-64]体系结构上的未初始化寄存器读取确实会产生垃圾结果,并且可能不会做任何坏事(与例如Itanium相反,其中寄存器可以被标记为无效 ,因此读取传播错误,如NaN)。

There are two main problems though: 但有两个主要问题:

  1. It won't be particularly random. 它不会特别随机。 In this case, you're reading from the stack, so you'll get whatever was there previously. 在这种情况下,你正在从堆栈中读取,所以你将获得之前的任何东西。 Which might be effectively random, completely structured, the password you entered ten minutes ago, or your grandmother's cookie recipe. 这可能是有效的随机,完全结构化,十分钟前输入的密码,或祖母的cookie配方。

  2. It's Bad (capital 'B') practice to let things like this creep into your code. 让(像''''''''''''''''''''''''''''''''''''''''' Technically, the compiler could insert reformat_hdd(); 从技术上讲,编译器可以插入reformat_hdd(); every time you read an undefined variable. 每次读取未定义的变量。 It won't , but you shouldn't do it anyway. 不会 ,但你不应该这样做。 Don't do unsafe things. 不要做不安全的事情。 The fewer exceptions you make, the safer you are from accidental mistakes all the time. 你所做的例外越少,就越安全意外错误所有的时间。

    The more pressing issue with UB is that it makes your entire program's behavior undefined. UB更紧迫的问题是它使整个程序的行为未定义。 Modern compilers can use this to elide huge swaths of your code or even go back in time . 现代编译器可以使用它来消除大量代码,甚至可以追溯到时间 Playing with UB is like a victorian engineer dismantling a live nuclear reactor. 与UB一起玩就像维多利亚时代的工程师正在拆除现场核反应堆。 There's a zillion things to go wrong, and you probably won't know half of the underlying principles or implemented technology. 有很多事情要出错,你可能不会知道一半的基本原则或实施技术。 It might be okay, but you still shouldn't let it happen. 可能没问题,但你仍然不应该让它发生。 Look at the other nice answers for details. 看看其他很好的答案细节。

Also, I'd fire you. 而且,我会解雇你。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值