Visual studio 2008 Visual Studio中的错误浮点处理?

Visual studio 2008 Visual Studio中的错误浮点处理?,visual-studio-2008,floating-point,epsilon,Visual Studio 2008,Floating Point,Epsilon,最后有一个更新 我有一个小故事 我想在MS Visual Studio 2008编译的C程序中计算机器ε(满足条件1.0+ε=1.0的最大ε>0)(在64位PC的Windows 7上运行)。因为我知道double和float有不同的精度,所以我想看看两者的答案。因此,我构建了以下程序: #include <stdio.h> typedef double float_type; int main() { float_type eps = 1.0; while ((float_t

最后有一个更新

我有一个小故事

我想在MS Visual Studio 2008编译的C程序中计算机器ε(满足条件1.0+ε=1.0的最大ε>0)(在64位PC的Windows 7上运行)。因为我知道double和float有不同的精度,所以我想看看两者的答案。因此,我构建了以下程序:

#include <stdio.h>
typedef double float_type;
int main()
{
  float_type eps = 1.0;
  while ((float_type) 1.0 + eps / (float_type) 2.0 > (float_type) 1.0)
    eps = eps / (float_type) 2.0;
  printf("%g\n", eps);
  return 0;
}
你会说这是个谜。哦,真正的谜团如下。比较:

  while ((float) (1.0 + eps / 2.0f) > 1.0f) 
给出了正确答案(1.19209e-07)和

给出的答案不适用于浮动,适用于双精度(2.22045e-16)

事实上,这是完全错误的,结果应该是相反的。这是因为默认情况下,编译器(根据标准)将1.0之类的常量视为double,如果它存在于算术表达式中,则所有其他操作数都将提升为double。相反,当我写入1.0时,所有操作数都是浮点数,不应进行升级。但我得到了一个完全不同的结果

在所有这些测试之后,我尝试使用gcc在Linux上编译和运行程序。毫不奇怪,它打印的正是我所期望的(正确答案)。所以我现在猜这是VisualStudio的bug。为了让大家开怀大笑(如果有人读过我的帖子,直到那一刻还有什么值得怀疑的),我将给你们另一个比较:

float c = 1.0;
while ((float) (c + eps / 2.0f) > 1.0f)
这在VS中无法正常工作,但是

const float c = 1.0;
给出1.19209e-07的正确答案

请有人告诉我,如果我是正确的,问题的根源是一个错误VS 2008编译器(你能确认你的机器上的错误?)。如果您在更新的版本:MS VS 2010中测试该案例,我也将不胜感激。谢谢

更新。
对于MS Visual Studio 2013,我提到的第一个程序没有意外的结果——它为float和double提供了适当的答案。我用所有浮点模型(精确、严格和快速)检查了这一点,没有任何变化。因此,在本例中,VS2008似乎确实存在缺陷。

默认情况下,Visual Studio的浮点设置设置为“精确”。这意味着它将努力使结果尽可能精确。这样做的一个副作用是,中间体的精度提高了一倍

虽然我没有仔细阅读您发布的所有代码,但我怀疑问题出在这里:

(float) (c + eps / 2.0f)
c+eps/2.0f
使用双精度完成。3个操作数中的每一个都提升为双精度,整个表达式的计算结果也是如此。当你投下它时,它只会四舍五入到一个浮点数


如果将浮点模式设置为“strict”,它将按预期工作。

谢谢您的评论。不幸的是,你提出的解决方案似乎不起作用。我尝试了浮点模型的所有类型的设置(快速、精确、严格),但都没有帮助。下面的程序(故意看起来荒谬)给出了错误的答案:#include int main(){float epsilon=1.0f;while((float)((float)1.0f+(float)((float)epsilon/(float)2.0f))>(float)1.0f)epsilon/=2.0f;printf(“%g\n”,epsilon);返回0;}这很有趣。如果将VisualStudio和GCC都设置为严格浮点模式,则它们应该始终给出相同的答案。(前提是程序中没有未定义的行为)如果没有,那么至少有一个编译器有bug.Wow。你回答我的评论的速度给我留下了深刻的印象^我在32位Windows机器上用MS VS 2008测试了我的程序,结果也不正确,所以我第一次在64位Windows上运行程序(同样是VS 2008)这一事实并不重要。gcc 4.4.3给出了正确的答案。嗯,我想我应该给某个微软论坛写信……我刚刚测试了你在评论中的例子。它在
严格
精确
模式下给出
1.19209e-007
。(我刚好在线,所以我会马上收到通知。)这很有趣。您是否使用了Microsoft Visual Studio 2008编译器?在哪个版本的Windows和哪个机器下?
float c = 1.0;
while ((float) (c + eps / 2.0f) > 1.0f)
const float c = 1.0;
(float) (c + eps / 2.0f)