floating-point - 在 k& 2 1中,解释这里代码

  显示原文与译文双语对照的内容
0 0

我试图确定各种浮点类型的范围。 当我读到以下代码:

#include <stdio.h>
main()
{
    float fl, fltest, last;
    double dbl, dbltest, dblast;
    fl = 0.0;
    fltest = 0.0;
    while (fl == 0.0) {
        last = fltest;
        fltest = fltest + 1111e28;
        fl = (fl + fltest) - fltest;
    }
    printf("Maximum range of float variable: %en", last);
    dbl = 0.0;
    dbltest = 0.0;
    while (dbl == 0.0) {
        dblast = dbltest;
        dbltest = dbltest + 1111e297;
        dbl = (dbl + dbltest) - dbltest;
    }
    printf("Maximum range of double variable: %en", dblast);
    return 0;
}

我不明白为什么作者添加 1111e28fltest变量?

时间:原作者:8个回答

0 0

循环终止时, fltest/ / / / / +Inf,因为这时 fl = (fl + fltest) - fltest成为 NaN,它是不等于 0.0. last包含一个值,这些属性在添加到 1111e28产生 +Inf所以接近的上限 float.

1111e28选择了到达 +Inf合理的日子,它还需要足够大,当添加到较大的值则继续循环进步我如果不包含。 它至少等于贫富差距最大和第二大非无限 float值。

原作者:
0 0

op : 。。。 为什么作者添加了 1111e28fltest变量?
a : [ Edit]代码的需要时, float, 1111e281.111e31增量值需要仔细选择。 应该大一些,这样,如果 fltestFLT_MAX之和, fltest + delta将导致溢出,并成为 float.infinity. 使用舍入到最接近模式,这是 FLT_MAX*FLT_EPSILON/4. 在我的机器上:

min_delta           1.014120601e+31 1/2 step between 2nd largest and FLT_MAX
FLT_MAX             3.402823466e+38
        FLT_EPSILON 8.388608000e+06
FLT_MAX*FLT_EPSILON 4.056481679e+31

delta需要足够小,所以如果 f1test是第2 大号,添加增量,反而会 sum一直存在 float.infinity并跳过 FLT_MAX. 我是3x min_delta

max_delta           3.042361441e+31

所以 1.014120601e+31 <= 1111e28 < 3.042361441e+31.

@david pfx Yes 。 1111e28是个很好玩的数字和它在范围内。

注: 在数学及其中间值,即使变量时发生并发症 float可能calcuate precsison喜欢较高 double. 这是C 中允许和控制。 FLT_EVAL_METHOD或者非常注意编码。


1111e28如果真是奇妙的值能不能理解作者准备好知道总的范围, FLT_MAX.

下面的代码在将循环次数( 24946069在一个测试平台) 。 不过幸运的是,值 fltest最终变为" 无限" 。 然后, f1将成为NaN为两者之差Infinity无穷大。 从0 .0 。作为NaN "While循环结束 ! @ecatmur

while (fl == 0.0) {
    last = fltest;
    fltest = fltest + 1111e28;
    fl = (fl + fltest) - fltest;
}

循环,如果足够小的增量中完成,就会得出一个准确的答案。 事先了解 FLT_MAXFLT_EPSILON因此需要确保这一点。

这个模式的问题在于C 未定义区域 FLT_MAXDBL_MAX而不是它们必须至少 1E+37. 所以如果是1111e28相当大,增量值,最大值或1111e297不会有任何的影响。 例如: dbltest = dbltest + 1111e297;,对于 dbltest = 1e400肯定不会增加1e400除非 dbltest有100位十进制数字的精度。

如果 DBL_MAX早到了小于1111e297,则该方法将失败。 注: 在简单平台在2014年并不奇怪 doublefloat相同,4 字节IEEE binary32 ) 尽管第一次循环, dbltest变为无穷大和循环停止,报告" 最大范围的double变量,请键入: 0 .000000e+00 " 。

有多种方法可以有效地获得的最大float点值。 下面是一个示例,它使用一个随机的初始值,以帮助其抵御潜在的变量显示 FLT_MAX.

float float_max(void) {
  float nextx = 1.0 + rand()/RAND_MAX;
  float x;
  do {
    x = nextx;
    nextx *= 2;
  } while (!isinf(nextx));
  float delta = x;
  do {
    nextx = x + delta/2;
    if (!isinf(nextx)) {
      x = nextx;
    }
    delta /= 2;
  } while (delta >= 1.0);
  return x;
}

isinf()是个新ish C 函数。 必要时足够简单展开你的。

在re : @didierc注释

[ edit]
精度 floatdouble隐式地与" epsilon " : " 之间的区别可表示为1,最小的值大于1,在给定的浮点类型的- - " 。 接下来 值最大

FLT_EPSILON 1E-5
DBL_EPSILON 1E-9

每个@Pascal Cuoq注释。 " 。。。 要选择好合适的大小大于FLT_MAX*FLT_EPSILON 。" 1111e28 1111e28需要至少 FLT_MAX*FLT_EPSILON之前影响循环数的加法,但是足够小到能够正好达到无穷大。 同样,事先了解 FLT_MAXFLT_EPSILON在需要做出判断。 如果这些值是提前已知,则代码简单可能是:

printf("Maximum range of float variable: %en", FLT_MAX);
原作者:
0 0

中可表示的最大值 float为3 .40282e+38 。 选择了不断1111e28以便将这个常量添加到范围内的数10^38仍会产生不同的浮点值,这样的值 fltest将继续增加,因为在函数运行。 它需要足够大,那还要有意义在10^38范围和圈子很小,结果将是准确的。

原作者:
...