我正在对用户的输入进行加密,以生成密码字符串。但是一行代码在框架的不同版本中给出了不同的结果。用户按下键值的部分编码:
按键: 1.变量ascii
为49。经过计算后的'e‘和'n’的值:
e = 103,
n = 143,
Math.Pow(ascii, e) % n
上述代码的结果:
.NET 3.5中的
Math.Pow(ascii,e) %n
提供9.0
.
Math.Pow(ascii,e) %n
提供77.0
.
Math.Pow()
在两个版本中都给出了正确(相同)的结果。
原因是什么?有解决方案吗?
发布于 2014-01-31 14:04:10
你看到的是双精度的舍入误差。Math.Pow
使用double,不同之处如下:
.NET 2.0和3.5 => var powerResult = Math.Pow(ascii, e);
返回:
1.2308248131348429E+174
.NET 4.0和4.5 => var powerResult = Math.Pow(ascii, e);
返回:
1.2308248131348427E+174
注意E
前面的最后一个数字,这是导致结果不同的原因。这不是模运算符,,,(%)
。
发布于 2014-01-31 14:00:13
浮点精度因机器和even on the same machine而异。
然而,.NET为你的应用程序创建了一个虚拟机...但是不同的版本会有所不同。
因此,您不应该依赖它来产生一致的结果。对于加密,请使用Framework提供的类,而不是使用自己的类。
发布于 2014-02-01 11:56:24
关于代码糟糕的方式,有很多答案。然而,对于为什么结果是不同的…
英特尔的FPUs在内部使用80位格式,以获得更精确的中间结果。因此,如果一个值在处理器寄存器中,它将获得80位,但当它被写入堆栈时,它将被存储在64位中。
我希望新版本的.NET在它的即时编译中有一个更好的优化器,所以它在寄存器中保留一个值,而不是将值写入堆栈,然后从堆栈中读回它。
可能JIT现在可以在寄存器中返回值,而不是在堆栈中返回值。或者将该值传递给寄存器中的MOD函数。
另请参阅堆栈溢出问题
其他处理器,例如ARM,将对此代码给出不同的结果。
https://stackoverflow.com/questions/21481764
复制相似问题