.Net内联数学调用在x64版本中产生无穷大
我很好奇是否有人可以复制这个问题,或者这只是我的机器的问题。如果我在发布模式下在控制台应用程序中运行以下代码,并且在Project Properties->Build下未选中“Preference 32-bit”选项,它将返回无穷大。但一旦我切换回首选32位,它就会返回0.1.Net内联数学调用在x64版本中产生无穷大,.net,x86,64-bit,.net,X86,64 Bit,我很好奇是否有人可以复制这个问题,或者这只是我的机器的问题。如果我在发布模式下在控制台应用程序中运行以下代码,并且在Project Properties->Build下未选中“Preference 32-bit”选项,它将返回无穷大。但一旦我切换回首选32位,它就会返回0.1 class Program { static void Main(string[] args) { TestClass t = new TestClass(); t.Test
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass();
t.Test(10);
Console.ReadKey();
}
}
public class TestClass
{
public void Test(int logarithmBase)
{
double min = 0.9;
Console.WriteLine(Math.Pow(logarithmBase, Math.Floor(Math.Log(min, logarithmBase))));
}
}
有趣的是,至少对我来说,如果我将对数基数改为双精度,那么它开始输出0.1。另外,如果我将数学调用字符串分解为单独的行,那么它也会输出0.1
我可以通过做我上面提到的一件事很容易地解决这个问题,但是如果有人能解释为什么它会这样做,那就太好了
编辑:这里是从IL反汇编程序对主函数和测试函数进行的反汇编,未选中“在模块加载时抑制JIT优化”。我比较了32位和64位版本的IL,从我所能看出,它看起来完全一样
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 19 (0x13)
.maxstack 8
IL_0000: newobj instance void TestingLog.TestClass::.ctor()
IL_0005: ldc.i4.s 10
IL_0007: callvirt instance void TestingLog.TestClass::Test(int32)
IL_000c: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_0011: pop
IL_0012: ret
} // end of method Program::Main
.method public hidebysig instance void Test(int32 logarithmBase) cil managed
{
// Code size 36 (0x24)
.maxstack 3
.locals init ([0] float64 min)
IL_0000: ldc.r8 0.90000000000000002
IL_0009: stloc.0
IL_000a: ldarg.1
IL_000b: conv.r8
IL_000c: ldloc.0
IL_000d: ldarg.1
IL_000e: conv.r8
IL_000f: call float64 [mscorlib]System.Math::Log(float64,
float64)
IL_0014: call float64 [mscorlib]System.Math::Floor(float64)
IL_0019: call float64 [mscorlib]System.Math::Pow(float64,
float64)
IL_001e: call void [mscorlib]System.Console::WriteLine(float64)
IL_0023: ret
} // end of method TestClass::Test
Edit2:从Visual Studio反汇编窗口反汇编,断点位于“min”变量定义上
double min = 0.9;
00007FFC8A7242D0 sub rsp,28h
00007FFC8A7242D4 xorpd xmm1,xmm1
Console.WriteLine(Math.Pow(logarithmBase, Math.Floor(Math.Log(min, logarithmBase))));
00007FFC8A7242D8 movsd mmword ptr [rsp+20h],xmm1
00007FFC8A7242DE xorps xmm1,xmm1
00007FFC8A7242E1 cvtsi2sd xmm1,edx
00007FFC8A7242E5 movsd xmm0,mmword ptr [7FFC8A724310h]
00007FFC8A7242ED call 00007FFCDA742B40
00007FFC8A7242F2 call 00007FFCE9E13D90
00007FFC8A7242F7 movaps xmm1,xmm0
00007FFC8A7242FA movsd xmm0,mmword ptr [rsp+20h]
00007FFC8A724300 call 00007FFCE9EA3820
00007FFC8A724305 call 00007FFCDA6E9E90
00007FFC8A72430A nop
00007FFC8A72430B add rsp,28h
00007FFC8A72430F ret
在反汇编之后(取消选中“在模块加载时禁用JIT优化”),我当然是指本机反汇编,但也有IL不会有什么坏处,希望这就是您所寻找的。抱歉花了这么长时间。是的,谢谢,它没有显示太多。不幸的是,或者至少我看不出有什么错。在64位的过程中,在线尝试它,得到的答案是0.1。32位浮点运算通常比64位浮点运算精度更高,但对于表达式而言,这不会有任何区别。我看不出如何从10^[Log10(0.9)]中得到无穷大,即使在考虑对数基数变化规则时,使用float也有足够的精度。您可以在另一台机器上尝试它,或者将部分结果存储到vars中吗?