【问题标题】:Round with floor problem in Objective-CObjective-C中的圆形地板问题
【发布时间】:2010-02-13 10:47:39
【问题描述】:

我正在用 e 和 s 计算 g,它们都是双精度数。之后我想截掉第二个之后的所有数字并将结果保存在x中,例如:

g = 2.123 => x = 2.12

g = 5.34995 => x = 5.34

等等。我用...

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

...而且它在大多数情况下都能正常工作。但有时我会得到奇怪的结果。例如:

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

所以我试图追查错误:

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

给我 g = 2.30

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

给我 g = 230.0

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

结果 x = 229.0 !!!

我不明白!请帮忙! :-)

【问题讨论】:

标签: c objective-c math floating-point


【解决方案1】:

这是由于浮点计算造成的。

你的计算

g * 100

已经带回来了

229.99999999999997

您的问题源于何处。

看看INFO: Precision and Accuracy in Floating-Point Calculations

也可以看看Floating point

准确性问题

浮点数的事实 不能精确地代表所有真实的 数字,以及那个浮点数 运算不能精确表示 真正的算术运算,导致 许多令人惊讶的情况。这是 与有限精度有关 计算机通常代表哪些 数字。

【讨论】:

【解决方案2】:

正如其他人已经提到的,这是由于计算机中浮点数的精度有限。这些不精确性在任何地方都会出现关于浮点数的硬是/否决定。为了解决这个问题,你可以加/减一个小数来找到一个正确的答案,达到一定的准确度。

您可能会发现这些函数很有用:

#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; }

当然,这些仅在有限的数量范围内有效。处理非常小或非常大的数字时,您需要为 ACC 选择另一个值。

请注意,“ACC”的值通常取决于应用程序中数字的准确性,而不是取决于 x 的值。例如,比较两个数字 ab 是否相等可以通过两种方式完成:isEqualAcc(a, b)isEqualAcc(a-b, 0)。您可能希望从两种方式获得相同的结果,即使在第二种方式中,数字 x 可能要小得多。

【讨论】:

  • 当然 ACC 应该是可计算的,而不仅仅是硬编码?如果我们知道x 的大小,我们不能确定潜在浮点错误的大小吗?
  • 我确实在 C 文档中注意到了 __FLT_EPSILON__;也许在这里有用。
  • ACC 几乎总是依赖于应用程序中数字的一般准确性,而不是相对于 x。请参阅答案中的附加说明。
【解决方案3】:

这是一种使用中间整数结果的可能方法:

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

【讨论】:

    猜你喜欢
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多