我想知道在以下假设下,下面定义的程序是否可以返回1:
在我看来,有时应该返回1,因为通常情况下
编辑: 我知道x的值在10^(-6)和10^6之间(这仍然留下了很多(太多)可能的双倍精度值,但我知道我不会遇到溢出、下溢或次正常数!此外,我刚刚意识到,由于
因此,问题对应于找到一个正常的双倍精度值
我写了一个小程序来尝试找到解决方案:
- 使用 IEEE754 浮点运算
- 没有溢出(在 max/x 和 f*x 中都没有)
- 没有 NaN 或 Inf(显然)
- 0 < x 且 0 < n < 32
- 没有不安全的数学优化
int canfail(int n, double x) {
double max = 1ULL << n; // 2^n
double f = max / x;
return f * x > max;
}
在我看来,有时应该返回1,因为通常情况下
roundToNearest(max / x)
可能大于max/x
。我能找到相反情况的数字,其中f * x < max
,但我没有例子表明f * x > max
,也不知道如何找到一个。有人可以帮忙吗?编辑: 我知道x的值在10^(-6)和10^6之间(这仍然留下了很多(太多)可能的双倍精度值,但我知道我不会遇到溢出、下溢或次正常数!此外,我刚刚意识到,由于
max
是2的幂,并且我们不涉及溢出,所以通过固定max=1
,解决方案将完全相同,但偏移了。因此,问题对应于找到一个正常的双倍精度值
x
,使得`(1/x)*x>1.0`!我写了一个小程序来尝试找到解决方案:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <omp.h>
int main( void ) {
#pragma omp parallel
{
unsigned short int xsubi[3] = {
omp_get_thread_num(),
omp_get_thread_num(),
omp_get_thread_num()
};
#pragma omp for
for(int64_t i=0; i<INT64_MAX; i++) {
double x = fmod(nrand48(xsubi), 1048576.0);
if(x<0.000001)
continue;
double f = 1.0 / x;
if(f * x > 1.0) {
printf("found !!! x=%.30f\n", x);
fflush(stdout);
}
}
}
return 1;
}
如果您改变比较的符号,您将很快找到一些值。然而,使用 f * x > 1.0
看起来似乎永远运行下去。
1 << n
不会溢出,但是您应该确保使用足够大的无符号类型来适应可能的位数,例如1ull << n
。 - user694733f
允许成为次正规数吗? - alias