简体   繁体   English

与Objective-C中的地板问题一起回合

[英]Round with floor problem in Objective-C

I am calculating g with e and s, which are all doubles. 我用e和s计算g,这些都是双打。 After that I want to cut off all digits after the second and save the result in x, for example: 之后我想在第二个之后切断所有数字并将结果保存在x中,例如:

g = 2.123 => x = 2.12 g = 2.123 => x = 2.12

g = 5.34995 => x = 5.34 g = 5.34995 => x = 5.34

and so on. 等等。 I Use... 我用...

g = 0.5*e + 0.5*s;
x = floor(g*100)/100;

...and it works fine most of the time. ......而且大部分时间都可以正常工作。 But sometimes I get strange results. 但有时我会得到奇怪的结果。 For example: 例如:

e = 3.0 s = 1.6 g = 2.30 but x = 2.29!!! e = 3.0 s = 1.6 g = 2.30但x = 2.29 !!!

So I tried to track down the error: 所以我试图追查错误:

g = 0.5*e + 0.5*s;
NSLog(@"%f",g);

gives me g = 2.30 给我g = 2.30

g = g * 100;
NSLog(@"%f",g);

gives me g = 230.0 给我g = 230.0

x = floor(g);
NSLog(@"%f",x);

results in x = 229.0 !!! 结果x = 229.0 !!!

I don't get it! 我不明白! Help please! 请帮忙! :-) :-)

This will be due to floating point calculations. 这将归因于浮点计算。

Your calculation 你的计算

g * 100

already brings back 已经带回来了

229.99999999999997 229.99999999999997

From where your issue stems. 您的问题源自何处。

Have a look at INFO: Precision and Accuracy in Floating-Point Calculations 看一下INFO:浮点计算的精度和准确度

Also have a look at Floating point 另请看浮点

Accuracy problems 准确性问题

The fact that floating-point numbers cannot precisely represent all real numbers, and that floating-point operations cannot precisely represent true arithmetic operations, leads to many surprising situations. 事实上,浮点数不能精确地表示所有实数,并且浮点运算不能精确地表示真正的算术运算,这会导致许多令人惊讶的情况。 This is related to the finite precision with which computers generally represent numbers. 这与计算机通常表示数字的有限精度有关。

As others have already mentioned, this is due to the limited precision of floating point numbers in computers. 正如其他人已经提到的那样,这是由于计算机中浮点数的精度有限。 These imprecisions show up everywhere a hard yes/no decision about a floating point number is made. 这些不精确现象出现在任何地方都有关于浮点数的艰难是/否决定。 In order to resolve the problem, you can add/subtract a small number to find an answer that is correct up to a certain accuracy. 为了解决问题,您可以添加/减去一个小数字,以找到一个正确的答案,达到一定的准确度。

You may find functions like these useful: 您可能会发现这些功能很有用:

#define ACC 1e-7

double floorAcc( double x ) { return floor(x + ACC);}
double ceilAcc( double x ) { return ceil(x - ACC); }
bool isLessThanAcc( double x, double y ) { return (x + ACC) < y; }
bool isEqualAcc( double x, double y ) { return (x + ACC) > y && (x - ACC) < y; }

Of course, these work only in a limited number range. 当然,这些只能在有限的范围内工作。 When working with very small or very large numbers, you need to pick another value for ACC. 使用非常小或非常大的数字时,您需要为ACC选择另一个值。

Note that the value of 'ACC' is in general dependent on the accuracy of the numbers in your application, not on the value of x. 请注意,'ACC'的值通常取决于应用程序中数字的准确性, 而不取决于x的值。 For example, comparing two numbers a and b for equality can be done in two ways: isEqualAcc(a, b) and isEqualAcc(ab, 0) . 例如,比较两个数字ab的相等性可以用两种方式完成: isEqualAcc(a, b)isEqualAcc(ab, 0) You would want the same result from both ways, even though in the second way the number x is likely much smaller. 您可能希望从两种方式获得相同的结果,即使在第二种方式中,数字x可能要小得多。

Here is a possible approach using intermediate integer results: 以下是使用中间整数结果的可能方法:

double e = 3.0;
double s = 1.6;

NSInteger e1 = e * .5 * 100.0; // 150
NSInteger s1 = s * .5 * 100.0; // 80

double x = (e1 + s1)/100.0; // 2.3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM