C 如何找到浮点、双精度、长双精度的最大值

C 如何找到浮点、双精度、长双精度的最大值,c,C,我是C和一般编程的新手。我必须想出一些算法来找出类型的大小,它的最大值和最小值。问题是我只能使用代码中给出的库(标准stdio.h、math.h和conio.h)。我想出了一个在C中使用溢出的主意。示例: { unsigned char c = -1; for (c; c < 0; c--); printf("%d\n", c); unsigned short s = -1; for (s; s < 0; s--); printf("%d\n", s); int i = -1; wh

我是C和一般编程的新手。我必须想出一些算法来找出类型的大小,它的最大值和最小值。问题是我只能使用代码中给出的库(标准stdio.h、math.h和conio.h)。我想出了一个在C中使用溢出的主意。示例:

{
unsigned char c = -1;
for (c; c < 0; c--);
printf("%d\n", c);
unsigned short s = -1;
for (s; s < 0; s--);
printf("%d\n", s);
int i = -1;
while (i < 0) {
    i = i - 1024;
}
printf("%d\n", i);
long l = -1;
while (l < 0)
{
    l = l - 1024;
}
printf("%d\n", l);
_getch();
return 0;
}
{
无符号字符c=-1;
对于(c;c<0;c-);
printf(“%d\n”,c);
无符号短s=-1;
对于(s;s<0;s-);
printf(“%d\n”,s);
int i=-1;
而(i<0){
i=i-1024;
}
printf(“%d\n”,i);
长l=-1;
而(l<0)
{
l=l-1024;
}
printf(“%d\n”,l);
_getch();
返回0;
}

所以这段代码查找无符号类型的最大值。但是我很难找到float、double和long double的值。

您的示例代码有几个问题,但这似乎不是您实际要问的问题。实际问题是关于实际类型的限制:

我很难找到float、double和long double的值

如果您必须在不依赖标准库的内置功能(主要是由
float.h
定义的各种宏)的情况下执行此操作,那么这确实很棘手。事实上,单靠算术是无法移植的,因为标准规定:

如果在表达式求值过程中出现异常情况(即,如果结果未在数学上定义或不在其类型的可表示值范围内),则行为未定义

(C2011,6.5/5;增加强调)

通过算术探测极限的唯一方法是发现结果超出范围的操作,但您无法通过便携方式识别这些操作,因为没有任何可靠的方法来识别未定义的行为(因为这样就可以定义行为)

如果无法使用
float.h
,则仍可以在以下情况下确定极限FP值:

  • 您假设实际类型使用带符号的IEEE-754类表示、大小和偏差未知的二元指数以及大小未知的二元尾数
  • 您假设类型
    uintmax\t
    的值位比任何实际感兴趣类型的尾数位都多
  • 假设每个实数类型的尾数位数不大于相应的最大指数加1;及
  • 您可以依赖数学函数
    ldexp
    (/
    ldexpf
    /
    ldexpl
    ),当要求计算超出范围的值时,该函数定义了行为
如果这些条件是可以接受的,那么请继续阅读

确定FP尾数大小 您可以通过执行从
uintmax_t
uintmax_t
的往返转换来确定尾数的位数,值具有不同的有效位数(并且没有尾随零)。能够在往返过程中保持不变的最大有效位数是被测FP类型尾数中的位数

确定FP指数范围 通过对第一个参数调用
ldexp()
,对第二个参数调用
1.0
,可以确定
double
的指数范围(例如)。不会导致范围错误发生的最大指数值是最大基数2指数。不会导致范围错误的最小(最负)值是大于最小指数减去尾数位数的值。您可以使用
ldexp
系列中相应的特定于类型的函数对其他实类型执行相同的操作

极限值的计算 给定实数类型的尾数大小
mbits
和指数限制
exp_max
exp_min
,可以这样计算限制值:

  • 最大值:构造一个
    uintmax\u t
    v
    ,将其
    mbits
    最低阶位设置为1,所有高阶位设置为0。计算最大值为
    ldexp(v,1+exp\u max-mbits)
    。想想为什么第二个参数是
    1+exp\u max-mbits
    而不是简单的
    exp\u max

  • 最小(正)规范化值:计算值为
    ldexp(1,exp\u min)
    。想想为什么第一个参数是1(或1.0),而不是
    v
    ,以及为什么计算不是

  • 最小(正)低于正常值:将该值计算为
    ldexp(1,1+exp\u min-mbits)
    。想想为什么第二个参数是
    1+exp\u min-mbits
    。如果使用
    exp_min-mbits
    ,必然会产生什么值

一般考虑 为确保编译器(如果符合)不会因任何类型的松散或转换优化而绊倒您,您可能需要写入相应实型的
volatile
变量,然后读回该变量的值。比如说,

uintmax_t probe = < some computation >;
volatile double converted = probe;
_Bool is_equal = (probe == (uintmax_t) converted);
uintmax\u t probe=;
挥发性双转换=探针;
_布尔等于(探测==(uintmax_t)转换);

此外,上述过程部分取决于能够识别
ldexp()
何时报告范围错误。这本身就有点难以移植,但这是一个完全不同的问题。

选择一种语言。两者都有不同的答案。看,这是你想要的。就用这个吧。你可以用的东西可能是重复的吗?除了算术以外的任何东西,比如
ldexp()
frexp()
函数族?你可以做什么样的假设?C对浮点表示的约束比对整数表示的约束要宽松得多,对FP行为的要求也相当宽松。”…还有这些技巧“-
sizeof