假设我有一些代码,例如:
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.0
和b=4.0
,那么ceil
的输出应该是5.00000
,但如果它是4.99999
呢?
类似的问题:100.0/4.0
是否有可能评估说5.00001
,然后ceil
会将其四舍五入到6.00000
?
我宁愿在整数数学中这样做,但sqrt
有点螺丝计划。
编辑:有关如何更好地实施此建议的建议也将受到赞赏! a
和b
值是整数值,因此实际代码更像是:ceil(sqrt(float(a)/b))
编辑:根据levis501的回答,我想我会这样做:
float a, b = ...; // both positive
int s = sqrt(a/b);
while (s*s*b < a) ++s;
谢谢大家!
答案 0 :(得分:6)
我不认为这是可能的。无论sqrt(a/b)
的值如何,它产生的是我们用作的一些值N:
int s1 = ceil(N);
int s2 = ceil(N) + 0.1;
由于ceil总是产生一个整数值(尽管表示为double),我们总会有一些值X,第一个产生X.0
,第二个产生X.1
。转换为int
将始终截断.1
,因此两者都会生成X
。
如果X太大以至于X.1溢出了double的范围,那么似乎会有例外。我不知道这可能在哪里。除了接近0(不考虑溢出)之外,数字的平方根将始终小于输入数字。因此,在ceil(N)+0.1溢出之前,a/b
中用作输入的sqrt(a/b)
必须已经溢出。
答案 1 :(得分:3)
您可能想为您的案例编写一个显式函数。 e.g:
/* 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
精度范围内的奇怪情况。
答案 2 :(得分:1)
浮点数的平等确实是一个问题,但如果我们处理整数,恕我直言。
如果您的情况为100.0/4.0
,那么它应该完全评估为25.0
,因为25.0
可以完全表示为浮点数,与...相反25.1
。
答案 3 :(得分:-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;
}
是的,这可以改进很多,这只是一个快速草图。
答案 4 :(得分:-2)
s1将始终等于s2。
C和C ++标准对数学例程的准确性没有太多说明。从字面上看,标准是不可能实现的,因为C标准说sqrt(x)返回x的平方根,但是2的平方根不能用浮点精确表示。
实现具有良好性能的例程,总是返回正确的舍入结果(在舍入到最接近的模式中,这意味着结果是最接近精确结果的可表示的浮点数,并且有利于a的关系低零位)是一个棘手的研究问题。好的数学库目标精度小于1 ULP(因此返回两个最接近的可表示数字之一),可能略高于.5 ULP。 (ULP是最小精度单位,低位的值在指数字段中给定特定值。)某些数学库可能比这更糟糕。您需要询问供应商或查看文档以获取更多信息。
所以sqrt可能略有偏差。如果确切的平方根是一个整数(在整数可以在浮点中精确表示的范围内)并且库保证错误小于1 ULP,那么sqrt的结果必须完全正确,因为除了确切的结果是至少1 ULP。
类似地,如果库保证错误小于1 ULP,则ceil必须返回确切的结果,因为确切的结果是可表示的,并且任何其他结果将至少为1 ULP。另外,ceil的本质是这样的,我希望任何合理的数学库总是返回一个整数,即使库的其余部分质量不高。
对于溢出情况,如果ceil(x)超出了所有整数都可以精确表示的范围,则ceil(x)+。1比任何其他可表示的数字更接近ceil(x),因此在实现浮点标准(IEEE 754)的任何系统中,将ce添加.1到ceil(x)的舍入结果应为ceil(x)。如果您处于默认的舍入模式,即舍入到最接近的模式。可以将舍入模式更改为round-to-infinity,这可能导致ceil(x)+。1为高于ceil(x)的整数。