简体   繁体   English

如何检测非 IEEE-754 浮点数,以及如何使用它们?

[英]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_MINFLT_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_iec559true对于所有浮点类型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 标准的修订版在C11C17/18中发生了变化,在C23 (草案)中将有许多与浮点相关的新宏,它(当前)指的是 ISO/IEC 60559:2020 和 IEEE 754-2019 包含对 IEC 60559:2011 / IEEE 754-2008 的小幅升级。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何输出IEEE-754格式的整数作为浮点数 - How to output IEEE-754 format integer as a float 如何将float转换为double(都存储在IEEE-754表示中)而不会丢失精度? - How to convert float to double(both stored in IEEE-754 representation) without losing precision? 将位打印为 IEEE-754 浮点数 - Printing bits as IEEE-754 float IEEE-754的浮点数,双精度数和四进制数是否保证精确表示-2,-1,-0、0、1、2? - Does IEEE-754 float, double and quad guarantee exact representation of -2, -1, -0, 0, 1, 2? 如何在C ++中将十六进制转换为IEEE 754 32位浮点 - How to convert Hex to IEEE 754 32 bit float in C++ 检查符号位的位置是否足以确定 IEEE-754 浮点数相对于 integer 字节序的字节序? - Is checking the location of the sign bit enough to determine endianness of IEEE-754 float with respect to integer endianness? 将 2 uint16_t 转换为 32-float IEEE-754 格式 - Converting 2 uint16_t to 32-float IEEE-754 fomat 32位,64位和80位浮点IEEE-754的可表示值范围? - Range of representable values of 32-bit, 64-bit and 80-bit float IEEE-754? 在C ++中编写符合IEEE-754标准的双/浮点分区的最快方法是什么? - What is the fastest way to write a IEEE-754 compliant double/float division in C++? cos(x) 是否需要在使用 IEEE-754 的不同 C++ 实现中返回相同的值? - Is cos(x) required to return identical values in different C++ implementations that use IEEE-754?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM