4

假设我有一些代码,例如:

float a, b = ...; // both positive
int s1 = ceil(sqrt(a/b));
int s2 = ceil(sqrt(a/b)) + 0.1;

有可能s1 != s2吗?我关心的是什么时候a/b是一个完美的正方形。例如,也许a=100.0and b=4.0,那么ceil应该是的输出,5.00000但是如果它是4.99999呢?

类似的问题:是否有机会100.0/4.0评估说5.00001然后ceil将其四舍五入6.00000

我更喜欢用整数数学来做这件事,但是这个sqrt计划有点搞砸了。

编辑:关于如何更好地实现这一点的建议也将不胜感激!和值是整数值ab所以实际代码更像:ceil(sqrt(float(a)/b))

编辑:根据 levis501 的回答,我想我会这样做:

float a, b = ...; // both positive
int s = sqrt(a/b);
while (s*s*b < a) ++s;

谢谢你们!

4

5 回答 5

6

我不认为这是可能的。不管 的值如何sqrt(a/b),它产生的都是一些值 N,我们将其用作:

int s1 = ceil(N);
int s2 = ceil(N) + 0.1;

由于 ceil 总是产生一个整数值(尽管表示为一个双精度值),我们总是有一些值 X,第一个产生一个X.0,第二个产生X.1。转换为int将始终截断它.1,因此两者都会导致X.

如果 X 太大以至于 X.1 超出了 double 的范围,似乎会有一个例外。不过,我看不出这在哪里是可能的。除了接近 0(溢出不是问题)外,数字的平方根将始终小于输入数字。因此,在 ceil(N)+0.1 可能溢出之前,a/b用作输入的 insqrt(a/b)必须已经溢出。

于 2011-11-02T17:34:05.820 回答
3

您可能想为您的案例编写一个显式函数。例如:

/* return the smallest positive integer whose square is at least x */
int isqrt(double x) {
  int y1 = ceil(sqrt(x));
  int y2 = y1 - 1;
  if ((y2 * y2) >= x) return y2;
  return y1;
}

这将处理比率的平方根a/b在精度范围内的奇怪情况double

于 2011-11-02T17:42:54.847 回答
1

浮点数的相等性确实是一个问题,但恕我直言,如果我们处理整数则不是。

如果你有 的情况100.0/4.0,它应该完美地评估为25.0,因为25.0它可以完全表示为一个浮点数,与 eg 相反25.1

于 2011-11-02T17:38:01.593 回答
-1

是的,完全有可能s1 != s2。为什么这是一个问题?这似乎很自然s1 != (s1 + 0.1)

顺便说一句,如果您希望5.00001四舍五入5.00000而不是6.00000,请使用rint代替ceil


并回答实际问题(在您的评论中) - 您可以使用sqrt获取起点,然后使用整数算术找到正确的平方。

int min_dimension_greater_than(int items, int buckets)
{
    double target = double(items) / buckets;
    int min_square = ceil(target);
    int dim = floor(sqrt(target));
    int square = dim * dim;
    while (square < min_square) {
        seed += 1;
        square = dim * dim;
    }
    return dim;
}

是的,这可以改进很多,这只是一个速写。

于 2011-11-02T17:33:25.123 回答
-2

s1 将始终等于 s2。

C 和 C++ 标准对数学例程的准确性没有太多说明。从字面上看,标准是不可能实现的,因为 C 标准说 sqrt(x) 返回 x 的平方根,但不能用浮点数精确表示 2 的平方根。

实现具有良好性能的例程,始终返回正确舍入的结果(在舍入到最近模式下,这意味着结果是最接近精确结果的可表示浮点数,并解决了有利于低零位的关系) 是一个困难的研究问题。好的数学库的目标精度小于 1 ULP(因此返回两个最接近的可表示数字之一),可能略高于 0.5 ULP。(ULP 是最低精度单位,即在指数字段中给定特定值的低位值。)一些数学库可能比这差得多。您必须询问您的供应商或查看文档以获取更多信息。

所以 sqrt 可能会稍微偏离。如果精确的平方根是一个整数(在整数可以用浮点数精确表示的范围内)并且库保证错误小于 1 ULP,那么 sqrt 的结果必须完全正确,因为除了确切的结果至少距离 1 ULP。

类似地,如果库保证错误小于 1 ULP,那么 ceil 必须返回准确的结果,同样因为准确的结果是可表示的,并且任何其他结果将至少 1 ULP 之外。此外, ceil 的性质是,我希望任何合理的数学库总是返回一个整数,即使库的其余部分质量不高。

至于溢出情况,如果 ceil(x) 超出了所有整数都可以精确表示的范围,那么 ceil(x)+.1 比任何其他可表示数字更接近 ceil(x),所以四舍五入的结果在任何实现浮点标准 (IEEE 754) 的系统中,将 .1 添加到 ceil(x) 应该是 ceil(x)。前提是您处于默认舍入模式,即舍入到最近。可以将舍入模式更改为类似于无穷大的舍入模式,这可能导致 ceil(x)+.1 为高于 ceil(x) 的整数。

于 2011-11-04T17:01:27.713 回答