我有一个简单的例程,它从浮点值计算宽高比.因此,对于值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".
我是C#的新手并且遇到了以下代码的问题(我的目标框架为4.5,我添加了对System.Numerics的引用):
using System;
using System.Numerics;
namespace Test
{
class Program
{
static BigInteger Gcd(BigInteger x, BigInteger y)
{
Console.WriteLine("GCD {0}, {1}", x, y);
if (x < y) return Gcd(y, x);
if (x % y == 0) return y;
return Gcd(y, x % y);
}
static void Main(string[] args)
{
BigInteger a = 13394673;
BigInteger b = 53578691;
Gcd(a, b);
}
}
}
Run Code Online (Sandbox Code Playgroud)
当通过调试启动发布版本时(Visual Studio中的F5 - 以及程序结束时的断点,以便我可以看到输出),我得到以下输出:
GCD 13394673, 53578691
GCD 53578691, 13394673
GCD 13394673, 13394672
GCD 13394672, 1
Run Code Online (Sandbox Code Playgroud)
但是,在没有调试(Ctrl-F5)的情况下启动发布版本时,我得到以下内容:
GCD …Run Code Online (Sandbox Code Playgroud) 我注意到C#编译器浮动舍入/截断有趣的行为.也就是说,当浮点字面值超出保证的可表示范围(7个十进制数字)时,则a)显式地将float结果转换为float(语义上不必要的操作)和b)将中间计算结果存储在局部变量中都会改变输出.一个例子:
using System;
class Program
{
static void Main()
{
float f = 2.0499999f;
var a = f * 100f;
var b = (int) (f * 100f);
var c = (int) (float) (f * 100f);
var d = (int) a;
var e = (int) (float) a;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
Console.WriteLine(e);
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:
205
204
205
205
205
Run Code Online (Sandbox Code Playgroud)
在我的计算机上的JITted调试版本中,b的计算方法如下:
var b = (int) (f * 100f);
0000005a fld dword ptr [ebp-3Ch]
0000005d fmul dword ptr ds:[035E1648h]
00000063 fstp qword …Run Code Online (Sandbox Code Playgroud) 我们有一些代码会在某些机器上产生意外结果.我把它缩小到一个简单的例子.在下面的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)
为什么会发生这种情况,是否有一种避免它的简单方法?与寄存器有关?
我们有一些单元测试可以检查方程线性系统解的结果,比较浮点数和delta.
尝试调整增量,我注意到Visual Studio Run test和Debug test模式之间的相同数字略有变化.
为什么会这样?当我调试测试时,#if DEBUG部分被禁用,因此执行的代码应该是相同的.
谢谢.