Visual Studio 2008和2013之间的浮点不匹配 [英] Floating point mismatch between Visual Studio 2008 and 2013

查看:186
本文介绍了Visual Studio 2008和2013之间的浮点不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将C ++项目升级到Visual Studio 2013之后,由于新VC编译器的浮点行为不同,程序的结果已更改.浮动模型设置为/fp:precise

After upgrading C++ project to Visual studio 2013, the result of the program has changed because of different floating point behavior of the new VC compiler. The floating model is set to /fp:precise

Visual Studio 2008(v9.0)

float f = 0.4f; //it produce f = 0.400000001
float f6 = 0.400000006f; //it produce f = 0.400000001

Visual Studio 2013(v12.0)

float f = 0.4f; //it produce f = 0.400000006                                 
float f1 = 0.40000001f; //it produce f1 = 0.400000006

项目的设置是相同的(已转换).

The setting for the project is identical (converted).

我知道浮点模型中存在一种自由,但是我不喜欢某些事情已经改变,使用旧版或新版Visual Studio的人无法重现由另一个人报告的一些错误开发人员.是否可以更改任何设置以在不同版本的Visual Studio中强制实施相同的行为?

I understand that there is a kind of liberty in floating point model, but I don't like that certain things has changed and the poeple working with old/new version of Visual Studio can't reproduce some bugs being reported by another developers. Is there any setting which can be changed to enforce the same behavior across different version of Visual Studio?

我试图将平台工具集设置为vs90,但在VS2013中仍然会产生0.400000006.

I tried to set platform toolset to vs90 and it still produce 0.400000006 in VS2013.

我在内存窗口"中跟踪了十六进制值.十六进制值f1,f1和f6都相同.在监视窗口中显示这些浮点值是有区别的.此外,问题还在于浮子0.3f.将相同的十进制值相乘会得出不同的结果.

I tracked the hexadicimal values in Memory Window. The hexadecimal values, f1, f1 and f6 are all the same. There is a difference in displaying these float values in the watch window. Futhermore the problem is still with float 0.3f. Multiplying same decimal values gives different result.

Visual Studio 2008(v9.0)

float a = 0.3f; //memory b8 1e 85 3e 00 00 40 40, watch 0.25999999
float b = 19400; 
unsigned long c = (unsigned long)((float)b * a); //5043

Visual Studio 2013(v12.0)

float a = 0.3f; //memory b8 1e 85 3e 00 00 40 40, watch 0.259999990
float b = 19400; 
unsigned long c = (unsigned long)((float)b * a); //5044

推荐答案

该行为是正确的, float 类型只能存储7个有效数字.其余只是随机噪声.您需要修复代码中的错误,或者显示太多数字,从而向人类揭示随机噪声,或者您的数学模型丢失了太多有效数字,您应该使用 double 代替.

The behavior is correct, the float type can store only 7 significant digits. The rest are just random noise. You need to fix the bug in your code, you are either displaying too many digits, thus revealing the random noise to a human, or your math model is losing too many significant digits and you should be using double instead.

VS2012中发生了重大变化,影响了噪声数字的外观.代码生成器的部分更改实现了自动矢量化.传统上,32位编译器使用FPU进行计算.对于产生不同的随机噪声,这是非常臭名昭著的,计算使用80位中间格式执行,并且在存储回内存时会被截断.由于优化器的选择,截断发生的确切时刻可能无法预测,从而产生不同的随机噪声.

There was a significant change in VS2012 that affect the appearance of the noise digits. Part of the code generator changes that implement auto-vectorization. The 32-bit compiler traditionally used the FPU for calculations. Which is very notorious for producing different random noise, calculations are performed with an 80-bit intermediate format and get truncated when stored back to memory. The exact moment when this truncation occurs can be unpredictable due to optimizer choices, thus producing different random noise.

与64位代码一样,代码生成器现在使用SSE2指令而不是FPU指令.它将产生更一致的结果,而不受代码优化器选择的影响,不再使用80位中间格式. 此答案中提供了有关FPU故障的背景知识.

The code generator, like it already did for 64-bit code, now uses SSE2 instructions instead of FPU instructions. Which produce more consistent results that are not affected by the code optimizer choices, the 80-bit intermediate format is no longer used. A backgrounder on the trouble with the FPU is available in this answer.

这将是继续的行为,FPU将再也不会回来.相应地调整您的期望,这是一个新常态".并修复错误.

This will be the behavior going forward, the FPU will never come back again. Adjust your expectations accordingly, there's a "new normal". And fix the bugs.

这篇关于Visual Studio 2008和2013之间的浮点不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆