[英]How to detect non IEEE-754 float, and how to use them?
I'm writing classes for basic types, so that code is logically the same on multiple platforms and compilers (like int_least16_t
for int
).我正在为基本类型编写类,因此代码在多个平台和编译器上在逻辑上是相同的(例如int_least16_t
for int
)。 For fun.为了娱乐。 (I'm still a student:) And I read this: (我还是个学生:)我读到这个:
float [...] Matches IEEE-754 binary32 format if supported. float [...] 匹配 IEEE-754 binary32 格式(如果支持)。
And what's worse:更糟糕的是:
Floating-point types MAY support special values: ∞ , NaN or -0浮点类型可以支持特殊值: ∞ 、NaN 或 -0
Which means that float MAY be unsigned...这意味着 float可能是无符号的......
[edit: Yes it's difrent thing, but there is no: ",but must suport negative numbers". [编辑:是的,这是不同的东西,但没有:“,但必须支持负数”。 Yo, with out things like this in standart it may not suport normal 0...(I don't have specyfication.) see ]哟,在标准中没有这样的东西它可能不支持正常的 0 ...(我没有规范化。) 见]
I know it's like with __int128 , and the standard is just a standard, but still... IEEE-754 is from 1985, but some machines can be weird, and some legacy hardware doesn't have a floating unit.我知道它就像__int128一样,标准只是一个标准,但仍然...... IEEE-754 来自 1985 年,但有些机器可能很奇怪,有些旧硬件没有浮动单元。
As I understand, float is mandatory (not optional like int16_t), but can be in any standard, and any set of values can be possible?据我了解,float 是强制性的(不像 int16_t 那样是可选的),但可以在任何标准中,并且任何一组值都是可能的?
Only thing we have are some macros ( <cfloat>
):我们唯一拥有的是一些宏( <cfloat>
):
FLT_MIN
, FLT_MAX
- Even if FLT_MIN = IEEE-754::FLT_MIN
, float can be non IEEE-754. FLT_MIN
、 FLT_MAX
- 即使FLT_MIN = IEEE-754::FLT_MIN
,浮点数也可以是非 IEEE-754。 For example float with: flipped exponent with fraction...例如 float with: flipped exponent with fraction...
FLT_RADIX
- Base system? FLT_RADIX
- 基本系统? If so, can help to write the exact value.如果是这样,可以帮助写出准确的值。 But still, float can be 3 bit or 200 bit (in size)...但是,float 仍然可以是 3 位或 200 位(大小)...
FLT_EPSILON
- (from 1 to next) We might use it (with base) to check fraction size... FLT_EPSILON
-(从 1 到下一个)我们可以使用它(带基数)来检查分数大小......
FLT_MANT_DIG
- Is it "mantissa" digits / fraction size? FLT_MANT_DIG
- 是“尾数”数字/分数大小吗?
FLT_MAX_EXP
- Exponent filled with 1... in IEEE-754, but outside can be a random number? FLT_MAX_EXP
- 在 IEEE-754 中用 1... 填充的指数,但外面可以是随机数?
If float is like IEEE-754 (sign, exponent, fraction), then it's easy, but if -0 and NaN are optional then it MAY be different.如果 float 类似于 IEEE-754(符号、指数、分数),那么它很容易,但如果 -0 和 NaN 是可选的,那么它可能会有所不同。 Because I can't tell them apart, I can't use bit representation (in a safe manner).因为我无法区分它们,所以我不能使用位表示法(以安全的方式)。 And if ∞ is optional, float
is no longer a safe type.如果∞是可选的,则float
不再是安全类型。
The only way out I see is to add macro to compiler.我看到的唯一出路是向编译器添加宏。
I know it's a theoretical problem, but I'm interested if there is any check possible or we all write implementation dependent code, when we use the float
keyword?我知道这是一个理论上的问题,但我感兴趣的是,当我们使用float
关键字时,是否有可能进行任何检查,或者我们都编写了依赖于实现的代码?
Edit 2022 May 04:编辑 2022 年 5 月 4 日:
I came up with this:我想出了这个:
User eg.用户例如。 code:代码:
//User eg. code:
int main()
{
float_M a = 1f;
float_M b = 0f;
std::cout << a/b; //should output infinty (IEEE-754)
}
//Code:
class float_M
{
public:
#ifdef __STDC_IEC_559__
float data;
//...
float_M operator/(float_M x){return float_M(data/x.data);}
//...
#else
/*union{
float data;
struct{//For noSign case ("absolutly catastrofic" case)
uint_least8_t sign : 1;
uint_least8_t exponent : 8;
uint_least32_t fraction : 23;
}
}*/ //no noSign case 🙂
float data;
//...
float_M operator/(float_M x){return divide(this, x);}
//funtion pointer alert!
static /*const (1*) */ float_M (*divide)(float_M a, float_M b) =
/*std::numeric_limits<float>::is_signed ?(*/
std::numeric_limits<float>::has_infinity ?(
std::numeric_limits<float>::has_quiet_NaN ?(
[]{return float_M(a.data/b.data);}
): &_divide_noNaN
): &_divide_noNaN
/*): &_divide_noSign*/
//...
#endif
}
It's ugly (have funtion pointer), but prevents unnesesery jumps at runtime.它很丑陋(有函数指针),但可以防止在运行时发生错误的跳转。 I hope c++23 will have better macros.我希望 c++23 有更好的宏。
Also, more links:另外,更多链接:
Follow-up: Can floats not suport negative后续: can float 不支持negative
In C++, the value of std::numeric_limits<T>::is_iec559
shall be true
for all floating-point types T
"if, and only if, the type adheres to ISO/IEC/IEEE 60559" and ISO/IEC/IEEE 60559:2011 is the same as IEEE 754-2008, so:在 C++ 中, std::numeric_limits<T>::is_iec559
的true
对于所有浮点类型T
“当且仅当该类型符合 ISO/IEC/IEEE 60559”和 ISO/IEC/IEEE 60559:2011 与 IEEE 754-2008 相同,因此:
#include <iostream>
#include <limits>
int main() {
std::cout << std::boolalpha << std::numeric_limits<float>::is_iec559 << '\n';
}
Note: As noted in the comments, some implementations may still report true
for this constant even though their floating point types are not following the IEEE 754-2008 standard to the letter.注意:如评论中所述,某些实现可能仍会报告此常量为true
,即使它们的浮点类型没有严格遵守 IEEE 754-2008 标准。
For example, in gcc
, you can compile with the options -Ofast
or -ffast-math
which in turn sets a number of options which can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions.例如,在gcc
中,您可以使用选项-Ofast
或-ffast-math
进行编译,这反过来会设置许多选项,对于依赖于 IEEE 或 ISO 数学规则/规范的精确实现的程序,这些选项可能会导致不正确的 output职能。
In C99 (and later), there are conditional feature macros, __STDC_IEC_559__
and __STDC_IEC_559_COMPLEX__
, that, if available in your implementation, will tell you if it's conforming to IEC 60559:1989 / IEEE 754−1985.在C99 (及更高版本)中,有条件功能宏__STDC_IEC_559__
和__STDC_IEC_559_COMPLEX__
,如果在您的实现中可用,它们将告诉您它是否符合 IEC 60559:1989 / IEEE 754−1985。
#include <stdio.h>
int main(void) {
#ifdef __STDC_IEC_559__
puts("true");
#endif
}
Note that if __STDC_IEC_559__
is not defined, it doesn't necessarily mean that the implementation doesn't use IEEE 754 floats.请注意,如果__STDC_IEC_559__
,并不一定意味着该实现不使用 IEEE 754 浮点数。 It could just mean that it doesn't have these conditional feature macros.这可能只是意味着它没有这些条件特征宏。 One interesting note about these macros is that if you use -Ofast
or -ffast-math
in gcc
, they will not be defined (unlike in the C++ test).关于这些宏的一个有趣的注意事项是,如果您在gcc
中使用-Ofast
或-ffast-math
,它们将不会被定义(与 C++ 测试不同)。
The actual revision of the IEC / IEEE standards used changed in C11 and C17/18 and in C23 (draft) there will be a number of new macros related to floating points and it (currently) refers to ISO/IEC 60559:2020 and IEEE 754-2019 which contains minor upgrades to IEC 60559:2011 / IEEE 754-2008.实际使用的 IEC/IEEE 标准的修订版在C11和C17/18中发生了变化,在C23 (草案)中将有许多与浮点相关的新宏,它(当前)指的是 ISO/IEC 60559:2020 和 IEEE 754-2019 包含对 IEC 60559:2011 / IEEE 754-2008 的小幅升级。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.