2017-02-28 236 views
5

我的程序中有一个奇怪的行为,其中双精度失去了精度。我的cout的显示正确的值,但仍然是行为意外。因此我调试和发现甚至gdb显示意外的值。 以下仅是简化方案:gdb显示不正确的double值

double length =2.11; 
//gdb shows 2.10 here but prints 2.11 correctly using cout at the end 
cout<<"length; //It prints 2.11 correctly here 

通常,这样的问题是很难找到生产场景中调试是不是一种选择,唯一的选择是使用尽可能多的打印成为可能。 任何建议如何避免这个问题?

+1

错误的问题(因为你忘了激励它,实际上有一些[XY问题](http://xyproblem.info)...)。正如你所评论的那样,你不会操纵*数字*,而是一些巴洛克长度表示(因为你评论说'2.11'意思是2英尺和11英寸) –

+1

如果你使用'double',一定要花几个小时才能读取http: //floating-point-gui.de/ –

+0

@BasileStarynkevitch:绝对好的建议。掌握了这些知识后,你们也会在派对上喋喋不休。 – Bathsheba

回答

6

假设IEEE754双精度浮点,最接近double至2.11是稍小

2.109999999999999875655021241982467472553253173828125

std::cout是足够聪明的默认适当圆形,但GDB似乎截断至2个小数位。

+0

我该如何避免这种情况?假设我有一个双变量作为'double var = 2.11',其中2代表feets和11英寸,我如何从中提取0.11部分,因为它总是使它成为10而不是11 – anurag86

+3

这是一个有问题的使用'double'而不是微不足道的解决。为什么不单独使用'struct'建模'feet'和'inches'?你甚至可以在它上面建立一个“标准化”方法,将1英尺13英寸转换为2英尺1英寸。 – Bathsheba

+2

有这样的表示是一个巨大的错误。 'double' *近似* [实数](https://en.wikipedia.org/wiki/Real_number)。你的数据甚至不是一个数字。或者(并且优选地)*将它转换为某种长度(例如,在*米*)或保留其他东西(一个'std :: string',一个'std :: pair ') –

2

鉴于实际数据的行为与您的情况一样,我担心没有太多要做。您可以计划避免它,并创建空间来对您的double值执行平等检查。

这里有你们两个似是而非的黑客:

1:在一所大学的项目尝试这样做]与数字打交道的顺序10^-4,用一个整数和一个因子值。例如:存储1.2345,存储整数12345和因子10000.现在您可以正确打印,这也可以进行平等检查。 2:如果已知双精度值的准确性,则可以使用偏移量。例如:如果2.109999具有2位小数的精度,请使用如下所示: (int)((2.109999 + .005)* 100)。然后相应地打印。

但是这两个黑客假定以下:

1:你对值的精确控制。 2:你真的需要打印准确的值。