32位和64位.NET(4)应用程序之间有什么区别?
通常,32位应用程序在64位计算机上运行时会出现问题,反之亦然.我知道我可以将整数声明为int32和int64(当然32位系统上的int64会产生问题).编程32 OR 64位或32位和64位兼容应用程序之间是否存在其他差异?
我有以下代码:
var d = double.Parse("4796.400000000001");
Console.WriteLine(d.ToString("G17", CultureInfo.InvariantCulture));
Run Code Online (Sandbox Code Playgroud)
如果我在Visual Studio中使用x86配置进行编译和运行,则会得到以下输出:
4796.4000000000005
Run Code Online (Sandbox Code Playgroud)
如果我改为编译为x64,则会得到以下信息:
4796.4000000000015
Run Code Online (Sandbox Code Playgroud)
我意识到使用32 och 64位编译必须影响系统处理double值的方式,但是考虑到C#将double定义为64位,因此该操作的结果不应该与我使用的编译配置无关地相同吗?
补充观察
基于对double.Parse的评论,我编写了以下代码:
var d0 = double.Parse("4796.400000000001");
double d1 = 4796.400000000001;
Console.WriteLine("d0: " + d0.ToString("G17", CultureInfo.InvariantCulture));
Console.WriteLine("d1: " + d1.ToString("G17", CultureInfo.InvariantCulture));
Run Code Online (Sandbox Code Playgroud)
当编译为x86时,我得到以下输出:
d0: 4796.4000000000005
d1: 4796.4000000000005
Run Code Online (Sandbox Code Playgroud)
但是当我编译为x64时,我得到了这个:
d0: 4796.4000000000015
d1: 4796.4000000000005
Run Code Online (Sandbox Code Playgroud)
请注意,值在x64版本中有所不同,但在x86版本中没有差异。
我偶然发现了在x86和x64的MS VS 2010版本之间完成浮点算术的方式不同(两者都在同一台64位机器上执行).
这是一个简化的代码示例:
float a = 50.0f;
float b = 65.0f;
float c = 1.3f;
float d = a*c;
bool bLarger1 = d<b;
bool bLarger2 = (a*c)<b;
Run Code Online (Sandbox Code Playgroud)
布尔bLarger1始终为false(在两个版本中d都设置为65.0).变量bLarger2对于x64为false,但对于x86为true!
我很清楚浮点算术和圆角效应正在发生.我也知道32位有时使用不同的指令进行浮动操作而不是64位构建.但在这种情况下,我错过了一些信息.
为什么bLarger1和bLarger2之间首先存在差异?为什么它只出现在32位版本上?

我有一个简单的例程,它从浮点值计算宽高比.因此,对于值1.77777779,例程返回字符串"16:9".我在我的机器上测试了它,它工作正常.
例程如下:
public string AspectRatioAsString(float f)
{
bool carryon = true;
int index = 0;
double roundedUpValue = 0;
while (carryon)
{
index++;
float upper = index * f;
roundedUpValue = Math.Ceiling(upper);
if (roundedUpValue - upper <= (double)0.1 || index > 20)
{
carryon = false;
}
}
return roundedUpValue + ":" + index;
}
Run Code Online (Sandbox Code Playgroud)
现在在另一台机器上,我得到了完全不同的结果.所以在我的机器上,1.77777779给出"16:9",但在另一台机器上我得到"38:21".
我们有一些代码会在某些机器上产生意外结果.我把它缩小到一个简单的例子.在下面的linqpad片段中,方法GetVal和GetVal2实现基本相同,尽管前者还包括对NaN的检查.但是,每个返回的结果都不同(至少在我的机器上).
void Main()
{
var x = Double.MinValue;
var y = Double.MaxValue;
var diff = y/10 - x/10;
Console.WriteLine(GetVal(x,6,diff));
Console.WriteLine(GetVal2(x,6,diff));
}
public static double GetVal(double start, int numSteps, double step)
{
var res = start + numSteps * step;
if (res == Double.NaN)
throw new InvalidOperationException();
return res;
}
public static double GetVal2(double start, int numSteps, double step)
{
return start + numSteps * step;
}
Run Code Online (Sandbox Code Playgroud)
结果
3.59538626972463E+307
Infinity
Run Code Online (Sandbox Code Playgroud)
为什么会发生这种情况,是否有一种避免它的简单方法?与寄存器有关?