我想知道以下定义的程序是否可以返回1:
max/x
和f*x
中都没有)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
答案 0 :(得分:4)
在没有下溢或上溢的情况下,指数是无关紧要的;如果为M/x*x > M
,则(M/p) / (x/q) * (x/q) > (M/p)
为两个p
和q
的任意幂。因此,让我们考虑2 52 ≤x
<2 53 和M
= 2 105 。我们可以消除x
= 2 52 ,因为这会产生精确的浮点运算,所以2 52 <x
<2 53 < / sup>。
将2 105 除以x
得到整数商q
和整数余数r
,其中2 52 {{1 }} <2 53 ,0 <{q
<r
和2 105 = x
•q
+ x
。
为了使r
超过M/x*x
,除法和乘法都必须四舍五入。由于该除法是四舍五入的,所以M
/ 2≤x
。
舍入后,将2 105 的浮点除以r
的结果将得出x
+ 1。然后,精确的(不是四舍五入的)乘法结果(q
+ 1)•q
= x
•q
+ x
= x
•{ {1}} + q
+ x
-x
= r
•r
+ q
+ x
-{{1 }} = 2 105 + r
-x
。由于r
/ 2 <x
,r
-x
≤r
/ 2,因此舍入该精确结果会舍入,得出2 105 < / sup>。 (由于2 105 具有低偶数位,因此,“ <”情况总是四舍五入,而“ =”情况则四舍五入。)
因此,对于两个x
的幂和所有在指数范围内的算术运算,r
永远不会发生从最近到最近的关系到偶数。
答案 1 :(得分:1)
乘以2的幂只是指数的缩放,它不会改变问题:因此,它与找到x
使得(1/x) * x > 1
一样。
一种解决方案是蛮力搜索。
出于相同的原因,我们可以将搜索x
的时间间隔限制为(1.0,2.0(
一种更好的方法是在没有暴力的情况下分析错误范围。
让我们注意ix
最接近1/x
的浮点。
将x
和ix
视为精确分数,我们可以写整数除法:1 = ix * x + r
其中r
是余数
(所有分母均为2的幂的分数,因此我们必须将整个方程乘以2的适当幂才能真正具有整数除法。)
换句话说,ix = 1/x - r/x
,其中-r/x
是求反的舍入误差。
当我们将逆近似值乘以x
时,精确值为ix*x = 1 - r
。
我们知道浮点结果将四舍五入到最接近该精确值的浮点数。
因此,假设默认舍入模式为最接近的,偶数为偶的,问的问题是-r
是否可以超过0.5 ulp
。
简短的回答永远不会!
假设|r| > 0.5 ulp
,那么舍入误差-r/x
确实超过了精确结果1/x
的一半。
这不是一个正确的答案,因为确切的结果不是浮点且没有ulp,但是您会明白...
如果有时间,我可能会带回正确的证明,但我敢打赌,您可能已经发现它已经完成了,也许是这样
编辑
为什么找到(1/x) * x < 1
?
仅因为1.0处于binade极限,所以低于1,我们必须证明r<0.25 ulp
,这是我们不能...
答案 2 :(得分:1)
canfail(1,pow(2,1023)*(2-pow(2,-51)))将返回1。