首页 > 解决方案 > 添加到 FLT_MAX 以导致溢出的最小数字

问题描述

我需要找到数字,它是 2 的幂,当添加到 FLT_MAX 时会导致溢出。但是,当我 printf 非常大的幂,比如 2^300,inf 仍然没有出现。另外,我认为由于 FLT_MAX 是表示的最大浮点数,因此将其加 1 会立即导致溢出。

#include <stdio.h>
#include <float.h>

int main(){
    float f = FLT_MAX;
    printf("%f", f + pow(2,300));
}

任何帮助,将不胜感激。谢谢!

标签: c

解决方案


答案是(FLT_MAX - nextafterf(FLT_MAX, 0))/2,即正好是 0x1p+103 或大约 1.014120480e+31。

您用来确定答案的方法有一个错误:标准函数pow返回 a double,而C 的“通常的算术转换”(C11 6.3.1.8:1)意味着表达式f + pow(2,300)被计算为 a double。然后将其打印为 a double,因为参数如何传递给可变参数函数。

这个 C 程序展示了如何float获得FLT_MAX通过float加法相加得到float无穷大的值:

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

int main(){
    float f = FLT_MAX;
    printf("FLT_MAX: %a\n", f);
    float b = nextafterf(f, 0);
    printf("number before FLT_MAX: %a\n", b);
    float d = f - b;
    printf("difference: %a\n", d);
    printf("FLT_MAX + d: %a\n", f + d);
    printf("FLT_MAX + d/2: %a\n", f + d/2);
    printf("FLT_MAX + nextafterf(d/2,0): %a\n", f + nextafterf(d/2,0));
    float answer = d/2;
    printf("answer: %a %.9e\n", answer, answer);
}

它打印:

FLT_MAX: 0x1.fffffep+127
number before FLT_MAX: 0x1.fffffcp+127
difference: 0x1p+104
FLT_MAX + d: inf
FLT_MAX + d/2: inf
FLT_MAX + nextafterf(d/2,0): 0x1.fffffep+127
answer: 0x1p+103 1.014120480e+31

它表明,如果您将FLT_MAX其与其较低邻居之间的差异(称为差异d),如您所料,d添加到FLT_MAXproductsinf中。但这不是float你可以添加到FLT_MAX生产中的最小的inf——还有更小的候选者。为了使结果达到 ,正好加上 的一半就足够d了。另一方面,如果您添加的值小于该值,则结果将向下舍入。FLT_MAXinfFLT_MAX


推荐阅读