【问题标题】:How many floating-point types are there in C?C中有多少种浮点类型?
【发布时间】:2023-02-22 00:14:29
【问题描述】:

许多程序员都知道 C 中有几种浮点类型。到目前为止,我知道 floatdoublelong double,但我不太确定它们是否全部,因为我找到了几个定义,如 @987654324 @.起初我以为这是 __FLT_MAX__ 的另一个名字,但当我尝试打印它时,我意识到它是不同的(如下所示):

#include <stdio.h>

void main(void)
{
    __mingw_printf("flt    value: %e, size: %d\n", __FLT_MAX__, sizeof(__FLT_MAX__));
    __mingw_printf("dbl    value: %e, size: %d\n", __DBL_MAX__, sizeof(__DBL_MAX__));
    __mingw_printf("ldbl   value: %e, size: %d\n", __LDBL_MAX__, sizeof(__LDBL_MAX__));
    __mingw_printf("dec32  value: %e, size: %d\n", __DEC32_MAX__, sizeof(__DEC32_MAX__));
    __mingw_printf("dec64  value: %e, size: %d\n", __DEC64_MAX__, sizeof(__DEC64_MAX__));
    __mingw_printf("dec128 value: %e, size: %d\n", __DEC128_MAX__, sizeof(__DEC128_MAX__));
}

/* output:
flt    value: 3.402823e+038, size: 4
dbl    value: 1.797693e+308, size: 8
ldbl   value: 3.237664e-317, size: 16
dec32  value: 9.944455e-315, size: 4
dec64  value: 9.089022e+269, size: 8
dec128 value: 3.237656e-317, size: 16
*/

什么是__十二月__*秒?
还有其他我不知道的浮点类型吗?

【问题讨论】:

  • 标准 C 有您列出的三个:floatdoublelong double。在某些系统上,doublelong double 可能相同。
  • 顺便说一句,要打印 long double 值,您应该使用格式说明符 %Le。格式说明符和参数类型不匹配会导致未定义的行为.要打印 size_t(这是 sizeof 的结果类型),您应该使用 %zu
  • 说到printf,你为什么使用非标准的__mingw_printf而不是标准的printf?与__FLT_MAX__ 等非标准常量类似,而不是标准的FLT_MAX?您使用哪些资源来学习 C?

标签: c types floating-point decimal


【解决方案1】:

在 C23 之前的 C 中只有 3 real floating-point typesfloatdoublelong double,它们可以使用任意基数作为有效数字,如十进制或八进制,尽管现在它很可能是二进制。一些较旧的系统使用hexadecimal floating-point types。每个真正的浮动类型都可以与 _Complex_Imaginary 关键字组合以创建复杂的浮动类型

C23添加了3 more real floating-point types_Decimal32_Decimal64_Decimal128,都是十进制类型

如果你看到其他任何东西编译器扩展或者内部编译器的东西.那些将以__为前缀,因为双下划线开头的标识符保留用于实现. __mingw_printf__DBL_MAX____DEC64_MAX__... 都是内部实现的,您不应该直接使用它们。使用FLT_MAX而不是__FLT_MAX__

事实上,在 C23 之前,GCC 中有一个 decimal floating extension

作为扩展,GNU C 支持 ISO/IEC WDTR24732 的 N1312 草案中定义的十进制浮点类型。 GCC 中对十进制浮点类型的支持将随着技术报告草案的变化而发展。任何目标的调用约定也可能发生变化。并非所有目标都支持十进制浮点类型。

十进制浮点类型是_Decimal32_Decimal64_Decimal128。它们使用基数 10,这与浮动类型 floatdoublelong double 不同,它们的基数未由 C 标准指定,但通常为 2。

6.14 Decimal Floating Types

由于 mingw 是 GCC 端口,它也支持十进制浮动扩展。通常在 float.h 中,标准常量将被定义为特定于实现的常量,例如

#define LDBL_MAX   __LDBL_MAX__
#define DEC128_MAX __DEC128_MAX__

【讨论】:

  • 除此之外,其他标准 FP 类型包括 complex floatcomplex double、...
  • @chux-ReinstateMonica 是的。我的意思是非复杂类型
【解决方案2】:

decimal 类型非常特殊,非常有趣,而且非常不标准(目前)。他们使用 internal fraction representation which is based on base 10,而不是基数 2。请特别参阅 IEEE 754-2008

因此,关于0.1 not being exactly representable0.1 + 0.2 not exactly equaling 0.3 的所有重要、不幸、令人厌烦的争论都消失了,几乎奇迹般地,计算机浮点数可以像我们都习惯的十进制浮点数一样运行!但是这些类型,以及它们需要的 printf 支持,还不是标准的、流行的或众所周知的。

在 IEEE 754-2008 中,两种主要的十进制类型是 decimal32decimal64,它们是我们熟悉的二进制 floatdouble 的十进制对应物。还有类似于long doubledecimal128


脚注:严格来说,说 decimal32 和其他是我们“熟悉的二进制”浮点类型(如 floatdouble)的“十进制对应物”并不完全正确。据我所知,新的小数类型确实保证是小数。但是传统类型 floatdoublelong double不是保证是二进制的。他们通常实际上,在您可能使用过的每台机器上,它们也可能是十进制的,在一种罕见的本机实现浮点且仅以十进制表示的旧机器上。在这样的机器上,您会注意到 FLT_RADIX 来自 &lt;float.h&gt; 是 10。

【讨论】:

  • 一些旧硬件甚至使用FLT_RADIX == 16
【解决方案3】:

某些特定用途需要小浮点数,例如:float8float16bifloat 它主要用于 DSP、AI 和图形应用程序。许多硬件架构至少支持其中的一些(例如 bifloat AVX-512 BF16、ARM-V8.8、AMD ROCm、CUDA 等)。

还有像 float128 这样的大浮点数格式。示例硬件:PowerPC 中的 VSX。

标准 C 不直接支持这些浮点数。一些编译器支持它作为扩展。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    相关资源
    最近更新 更多