0

我正在尝试运行我的程序并且我正在使用

double result = cos(90*M_PI/180);
NSLog("Cos 90 value %g",result);  //Prints 6.12323e-17

但是当我运行这个

 NSLog("Cos 90 value %f",cos(90*M_PI/180)); //Prints 0

我想在 result(double) 中得到 cos90 的值,它应该是 0。我知道那是浮点运算问题。但是如何解决它。有什么办法吗?

谢谢

4

3 回答 3

1

由于 的参数cos是弧度,要计算 90º 的余弦,您将传递 π/2 弧度。π/2 约为 1.570796326794896619。最接近 π/2 的 IEEE 754 双精度约为 1.570796326794896558。显然,这些是不同的。后者的余弦约为 6.123•10 -17。因此,您的余弦例程工作正常;它返回它传递的数字的余弦。

将 π/2 传递给 是不可能的cos,因为 π/2 不能表示为双精度数。

根据您的要求,可能会有解决方法。例如,此表达式将(近似)返回 x 的余弦(以度为单位),并且当 x 为 90 时将精确为零:sin(M_PI/180*(90-x))

于 2012-11-16T02:19:05.590 回答
0

问题是结果太小了。唯一的区别是格式说明符。%g并且%f是不同的;%f通常在小数点后有六点精度,而%g使用科学计数法表示小数。您可以使用 扩展小数点后打印的字符数%.100f,其中100是小数点后的字符数。但是,这不是很精确,并且在小数点后不能保证精度

编辑:嗯,现在我注意到你实际上想要计算的是什么。它不是零,因为由于舍入等原因,该级别的浮点运算不精确。

于 2012-11-15T18:03:25.117 回答
0

最后我找到了解决方案。所有的解释都是正确的,但是这个问题的“临时”解决方案是NSNumberFormatter.

NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];

[formatter setAlwaysShowsDecimalSeparator:NO];
[formatter setAllowsFloats:YES];
[formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[formatter setMinimumFractionDigits:0];
[formatter setMaximumFractionDigits:10]; //THIS IS IMPORTANT AS AFTER DECIMAL, DIGITS SHOULD BE LESS THAN 17 because there is difference of 6.12323e-17 

double result = cos(90*M_PI/180);
NSNumber *numberResult = [NSNumber numberWithDouble:result];

[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSLog(@"%@",[formatter stringFromNumber:number]); //Prints 0

这是一个临时解决方案。您也可以使用 %f 打印 cos 90 的值,但它也会在小数点后打印不需要的六个 0。

于 2012-11-19T17:55:08.343 回答