Visual Studio 2010中的精度问题

4

我有一个使用Microsoft Visual C++ 6.0编写的应用程序。现在,我已经使用C#在Visual Studio 2010中重写了该应用程序,但由于精度问题,结果不匹配。其中一个这样的精度问题是以下问题。

float a = 1.0f;

float b = 3.0f;

float c = a / b;

这是在 Visual Studio 2010 中运行的 C# 代码,返回值 c 的值为 0.333333343

但是,当使用 Visual C++ 6.0 运行同样的代码时,在值定义中将 f 去除后,c 的值为 0.333333

有人能够解决这个问题并解释如何在 Visual Studio 和 Visual C++ 6.0 中获得相同的 c 值吗?


实际上,这些值来自观察窗口。我得知不同版本的 Visual Studio 可能在浮点格式表示方面存在差异。因此,观察窗口中的值可能没有用处。这就是为什么我在两个 Visual Studio 版本中打印了值的原因,结果如下。 在使用 Visual C++ 语言的 Visual Studio 6.0 中,它为 0.333333(六个3)

但是在使用 C# 语言的 Visual Studio 10 中,它为 0.3333333(七个3)。

那么,有谁能帮助我使我的 C# 程序产生与 Visual C++ 相同的结果吗?(即,如何使浮动操作在两个版本上产生相同的结果?)


2
你是如何查看这些值的?我非常确定内部表示是相同的(除非我错了,C#在幕后使用double),但是显示数字给用户的方法不同,所以你可能只是看到了不同的显示默认值。 - Mr Lister
@MrLister,C# 4.0规范在第4.1.6节中指出,浮点数的二元操作“至少使用float的范围和精度”(强调添加)。因此,后台精度是实现定义的。.NET Framework很可能在幕后使用双精度。 - phoog
4个回答

15
考虑到确切的值是0.3循环,两者都不是“正确”的 - 如果您试图匹配二进制浮点计算的确切结果,这通常是一个不好的开始,因为它们的工作方式。 (有关更多信息,请参见我的 .NET中的二进制浮点文章。)
可能您在第一次使用二进制浮点时不应该使用它(例如,如果您的值表示精确的人造金额),或者仅应使用特定容差进行等式比较。
还有可能C#和C生成相同的位模式 - 但由于这些值的格式,您会看到不同的结果。 同样,我不会使用数字的文本表示进行比较。

我已经打印了这两个值,使用 Visual C++ 得到了 0.333333(六个3),而使用 C# 则得到了 0.3333333(七个3)。这意味着存在错误。我该如何让 Visual C++ 6.0 和 Visual Studio 10 with C# 产生相同的结果? - Mahesh
@Mahesh:不,这并不意味着有错误。我怀疑这只是每种情况涉及的文本格式问题。 - Jon Skeet

5

C# 仅仅显示少数的小数位。 0.333333343 四舍五入到六个有效数字是 0.333333。变量 c 的真实值并没有改变。

当然,如果你需要更高的精度,你可以使用 double 变量。


3

C#浮点数可以通过floatdouble类型处理。一个float类型的精度为7位数字,而double类型的精度为16位。

我相信C++标准的精度约为16位数字(平均为15.9!)。

无论如何,这两种表示方法都不是算术上正确的,因为1/3是0.333循环。

我认为你看到的只是该值的表示方式(请注意,调试器将把该值转换为字符串进行显示。如果您检查每个内存位置,您可能会发现这些值是相同的。


1
一个快速的检查表明,是的,这些数字完全相同。所以你的问题的答案是,当你想要相同的输出时,你只需要确保显示方法是兼容的。
例如,在C中使用printf("%9.7f", result),在C#中使用string.Format("{0:0.0000000}", result)。就是这样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接