如果所有浮点数都表示为x = (-1)^s * 2^e * 1.m
,则在没有特殊情况支持的情况下无法存储零。
答案 0 :(得分:8)
不,所有符合要求的C实现都必须支持浮点值0.0
。
浮点模型在C standard的5.2.4.2.2节中描述(链接是最近的草稿)。该模型不会使有效数(有时称为尾数)中的前导1
隐式,因此表示0.0
没有问题。
二进制浮点数的大多数实现都不存储前导1
,实际上是您在问题中引用的公式:
x = (-1)^s * 2^e * 1.m
通常是正确的(尽管存储e
的方式可能不同)。
在包括IEEE的此类实现中,使用特殊情况位模式(通常为全位 - 零)来表示0.0
。
继续评论中的讨论,tmyklebu认为并非所有由5.2.4.2.2中的浮点模型定义的数字都必须是可表示的。我不同意;如果不是所有这些数字都需要可表示,那么该模型几乎是无用的。但即使抛开这个论点,也明确要求0.0
必须是可表示的。 N1570 6.7.9第10段:
如果具有静态或线程存储持续时间的对象不是 显式初始化,然后:
- ...
- 如果它有算术类型,则初始化为(正数或无符号)零;
- ...
这是一个非常长期的要求。 C reference from 1975(K& R1出版前3年)说:
未明确初始化的任何外部定义对象的初始值保证为0.
这意味着必须有一个可表示的0值。 K& R1(1978年出版)说,第198页:
保证未初始化的静态和外部变量 从0开始;自动和寄存变量不是 初始化保证以垃圾开始。
有趣的是,1990 ISO C标准(相当于1989 ANSI C标准)略逊于其前身和后继者。在6.5.7中,它说:
如果未初始化具有静态存储持续时间的对象 显式地,它被隐式初始化,好像每个成员都有 算术类型被赋值为0,每个成员都有指针类型 被分配了一个空指针常量。
如果浮点类型不需要具有0.0
的精确表示,则"分配0"短语意味着从int
值0
转换为浮点类型,产生一个小值 close 到0.0
。尽管如此,C90具有与C99和C11相同的浮点模型(但没有提及次正规或非标准化值),我上面关于模型数的论证仍然适用。此外,C90标准正式被C99取代,而C99又被C11取代。
答案 1 :(得分:2)
搜索一段时间后发现了这个。
ISO / IEC 9899:201x第6.2.5节,第13段
每个复杂类型都具有与数组相同的表示和对齐要求 类型恰好包含相应实数类型的两个元素;第一个要素是 等于复数的实部和虚部的第二个元素。
第6.3.1.7节,第1段
当真实类型的值转换为复杂类型时,复数的实部 结果值由转换为相应实数类型的规则确定 复数结果值的虚部是正零或无符号零。
所以,如果我理解这一点,任何支持C99(带有_Complex类型的第一个C标准)的实现都必须支持浮点值0.0。
修改强> Keith Thompson指出复杂类型在C99中是可选的,所以这个论点毫无意义。
答案 2 :(得分:1)
我相信以下浮点系统是一个符合浮点运算的例子,没有零表示:
float
是一个48位数,带有一个符号位,15个指数位和32个有效位。符号位,指数位和有效位的每个选择都对应于具有隐含前导1
位的正常浮点数。
完成draft C standard Keith Thompson linked的第5.2.4.2.2节中的约束:
-0x1.ffffffffp+16383
到0x1.ffffffffp+16383
。+
,-
,*
,/
和数学库具有实现定义的准确性。还行。FLT_ROUNDS
设置为0;这样,我甚至不必指定加法或减法溢出时会发生什么。FLT_EVAL_METHOD
应为0。FLT_HAS_SUBNORM
应为零。FLT_RADIX
应为2,FLT_MANT_DIG
为32,FLT_DECIMAL_DIG
为10,FLT_DIG
为9,FLT_MIN_EXP
为-16383,{ {1}}应为-4933,FLT_MIN_10_EXP
应为16384,FLT_MAX_EXP
为4933。FLT_MAX_10_EXP
,FLT_MAX
,FLT_EPSILON
和FLT_MIN
。