Closed. This question needs to be more focused。它当前不接受答案。
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
                        
                        3年前关闭。
                                                                                            
                
        
我是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;
}


因此,此代码查找无符号类型的最大值。但是我很难找到float,double和long double的值。

最佳答案

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


  我很难找到float,double和long double的值。


如果您必须在不依赖标准库的内置功能的情况下(大多数情况下是由float.h定义的各种宏)来执行此操作,那确实很棘手。实际上,仅凭算术就不能完全做到这一点,因为该标准规定:


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


(C2011,6.5 / 5;添加了重点)

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

如果您不能使用float.h,则仍然可以确定FP极限值,如果


您假定实类型使用带符号的类IEEE-754表示形式,具有未知大小和偏差的二进制指数以及具有未知大小的二进制尾数;
您假设uintmax_t类型的值位比任何感兴趣的实际类型的尾数位都多;
您假设每种实型的尾数位数不大于相应的最大指数加一;和
您可以依靠数学函数ldexp(/ ldexpf / ldexpl),该函数定义了当要求计算超出范围的值时的行为。


如果这些条件可以接受,请继续阅读...。

确定FP尾数大小

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

确定FP指数范围

例如,可以通过将double与第一个参数调用ldexp()并为第二个参数使用各种值来确定1.0的指数范围。不引起范围误差发生的最大指数值是最大基数2指数。不会引起范围误差的最小(最大负值)值大于最小指数减去尾数位数。您可以使用ldexp系列中适当的特定于类型的函数,对其他实际类型执行相同的操作。

计算极限值

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


最大值:构造一个uintmax_tv,将其mbits最低位设置为1,并将其所有高位设置为0。将最大值计算为ldexp(v, 1 + exp_max - mbits)。考虑为什么第二个参数是1 + exp_max - mbits而不是简单的exp_max
最小(正)归一化值:将值计算为ldexp(1, exp_min)。考虑一下为什么第一个参数是1(或1.0)而不是v,以及为什么计算不是...
最小(正)子正常值:将值计算为ldexp(1, 1 + exp_min - mbits)。考虑为什么第二个参数是1 + exp_min - mbits。如果改用exp_min - mbits,必然会得到什么值?


一般注意事项

为确保编译器(如果符合)不会使您感到松懈或对转换进行优化,则可能要写入适当实型的volatile变量,然后再读回值该变量。例如,

uintmax_t probe = < some computation >;
volatile double converted = probe;
_Bool is_equal = (probe == (uintmax_t) converted);


另外,以上过程部分取决于能否识别ldexp()报告范围错误。这样做本身有点棘手,但这是另一个问题。

关于c - 如何找到float,double,long double的最大值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40183011/

10-11 22:51
查看更多