C语言 2个连续双精度数之间的差(下一个可表示的双精度数)

0qx6xfy6  于 2023-04-05  发布在  其他
关注(0)|答案(1)|浏览(110)

我试图计算给定的double和下一个可表示的double之间的差异(或者最小的double数加上给定的数字会改变值)

#include <stdio.h>
#include <math.h>

double f1(double a)
{
   double diff=1.0,num=fabs(a);

   while(num+(diff/2.0)>num )
    {
     diff/=2.0 ;
    }
   while(num+(diff*2.0)==num)
    {
     diff*=2.0 ;
    }
   return diff  ;
}

double f2(double a)
{
  int e=log2(fabs(a)) ;
  double diff=pow(2,-52+e) ;
  return diff ;
}

int main()
{
    double num ;
    //printf("Enter number:") ; scanf("%le",&num) ;
    double diff=nextafter(num,INFINITY)-num ;
 
    printf("f1=%le\n",f1(num)) ;
    printf("f2=%le\n",f2(num)) ;
    printf("difference=%le\n",diff) ;
    if(num+f1(num)/2.0==num) printf("Equal1\n") ;
    if(num+f2(num)/2.0==num) printf("Equal2\n") ;
   
    return 0;
}`

似乎我的f2()函数返回的值等于我使用nextafter()函数计算的差值。F1()函数有时
返回值等于f2(),有时返回值小于f2()的2倍。
但是检查“if”条件会发现f1()返回的值是两个连续double之间的实际差值,因为num+f1(num)/2.0==num和num+f2(num)/2.0!=num。
那么为什么有时候(例如num=199.23999)f1()!=f2()?我做错了什么?

kokeuurv

kokeuurv1#

f1不查找 a 与下一个可表示数之间的差值(在更大幅度的方向上)。它查找2 x 的最小幂,使得|a|而 x 不会产生|a|.
如果 a'是 a 之后的下一个可表示数,那么 *a *'-a 就是它们之间的差,并且将 *a *'-a 加到 a 上会产生 *a *'。但是这并不意味着将(*a *'-a)/2加到 a 上不会产生 *a *'。是否会产生 * a *'取决于舍入。
在实数算术中,(*a *'− a)/2和 a 的和是 a 和 *a *'之间的中点。默认的舍入规则是向最近的可表示值舍入,当有平局时,向最近的可表示值舍入,该值的有效位数为偶数。
考虑三个连续的可表示数1+0·2−52,1+1·2−52和1+2·2−52。当我们将2−53加到1+0·2−52时,实数算术和为1+0.5·2−52,并且两个最近的可表示值为1+0·2−52和1+1·2−52。其中,前者具有偶数低位,所以浮点加法产生它作为结果。当我们将2−53与1+1·2−52相加时,实数算术和为1+1.5·2−52,并且两个最接近的可表示值为1+1·2−52和1+2·2−52。其中,后者具有偶数低位,因此浮点加法产生它作为结果。
这意味着对于输入1+0·2−52,f1产生2−52,因为2−52加1+0·2−52产生1+1·2−52,而2−53加1 + 1·2 − 52不产生1 + 1·2− 52;对于输入1+1·2−52,f1产生2−53,因为2−53加1+2·2−52(而2− 54加1 + 2·2−54不产生1)。

相关问题