C++ 独立于实现的浮点/整数转换
假设C++ 独立于实现的浮点/整数转换,c++,c,language-lawyer,C++,C,Language Lawyer,假设I是某种整数类型,而F是某种(实)浮点类型 我想写两个函数。第一个函数应取类型为i的值i,并返回一个布尔值,指示转换为F的i是否属于可表示范围,即(F)i是否具有定义的行为 第二个函数应取类型为f的值f,并返回一个布尔值,指示转换为I的f是否属于可表示范围,即(I)f是否具有定义的行为 是否有可能编写这样一个函数,在每个符合标准的实现上都是正确的,并且对于任何输入都不会表现出未定义的行为?特别是,我不想假设浮点类型是IEEE 754类型 我分别询问C和C++以及它们各自的标准版本,如果改变了
I
是某种整数类型,而F
是某种(实)浮点类型
我想写两个函数。第一个函数应取类型为i
的值i
,并返回一个布尔值,指示转换为F
的i
是否属于可表示范围,即(F)i
是否具有定义的行为
第二个函数应取类型为f
的值f
,并返回一个布尔值,指示转换为I
的f
是否属于可表示范围,即(I)f
是否具有定义的行为
是否有可能编写这样一个函数,在每个符合标准的实现上都是正确的,并且对于任何输入都不会表现出未定义的行为?特别是,我不想假设浮点类型是IEEE 754类型
我分别询问C和C++以及它们各自的标准版本,如果改变了答案,
基本上,这个问题的目的是要弄清楚(合理的)浮点/积分转换是否可能,而完全不依赖IEEE 754或其他标准或硬件细节。我问是出于好奇 与例如INT\u MAX
或FLT\u MAX
进行比较似乎是不可能的,因为在不知道哪种类型的范围更大的情况下,不清楚要在哪种类型中进行比较。一些浮点到一些INT相当容易,因为我们可以假设FLT\u基数!=10
(2N浮点)且FP的范围超过整数范围
形成精确的FP限制测试FP的分数部分是否为0**。(也处理NaN、inf)
如果太阳性,则进行检测。
如果太阴性,则进行测试。
测试是否转换为整数值舍入 伪码
// For now, assume 2's complement.
// With some extra macro magic, could handle all integer encodings.
// Use integer limits whose magnitudes are at or 1 away from a power-of-2
// and form FP power-of-2 limits
// The following will certainly not incur any rounding
#define FLT_INT_MAXP1 ((INT_MAX/2 + 1)*2.0f)
#define FLT_INT_MIN (INT_MIN*1.0f)
status float_to_int_test(float f) {
float ipart;
if (modff(f, &ipart) != 0.0) {
return not_a_whole_number;
}
if (f >= FLT_INT_MAXP1) return too_big;
if (f < FLT_INT_MIN) return too_negative;
if (f != (volatile float) f)) return rounding_occurred;
return success;
}
简化是可能的,但是要开始做一些事情 需要额外代码的极端情况包括
int128\u t
或范围大于float
和FLT\u基数==10
**Hmmm-似乎OP不关心分数部分。在这种情况下,对于一半的问题来说是一个很好的重复。
std::numeric_limits
应该为您提供所需的所有信息,以了解这些值是否可转换(需要进行计算)。@NathanOliver,我不确定应该使用什么进行比较。正如我提到的,我认为我无法与max
进行比较,因为这已经需要将操作数转换为该类型,这可能是不可能的。我可以将整数的log2与max_指数
进行比较,但我不确定当它们比较相等时是否能得出任何结论。相关的,甚至是一个duplicate@GreenTree谢谢,我一定是找错词了。这个问题和其他相关的问题似乎是重复的。但是我仍然需要详细阅读它们。仅仅做双向转换和检查相等性有什么问题吗?我很难想象这样做会失败。是的,我对分数部分不感兴趣。我认为,I
的范围可能大于F
的范围是有问题的。链接的问题并不能完全回答这个问题,但我想可以认为是重复的。如果有人想以复制品的形式关闭它,我会同意的。@U标记是的,“我比F的大”是很棘手的-我稍后会补充一些东西-现实生活正在召唤我离开。处理“对小数部分不感兴趣”。
status int_to_float_test(int i) {
volatile float f = (float) i;
if (float_to_int_test(f) != success) return fail
volatile int j = (int) f;
if (i != j) return fail;
return success;
}