C++ 双精度0.0是否总是在可移植C中精确表示?
以下代码是否可以在所有具有符合ANSI标准的C编译器的环境中工作C++ 双精度0.0是否总是在可移植C中精确表示?,c++,c,bit-representation,inexact-arithmetic,C++,C,Bit Representation,Inexact Arithmetic,以下代码是否可以在所有具有符合ANSI标准的C编译器的环境中工作 double n = 0; assert(n == 0); < C++ > C99不强制IEEE75,只推荐它。符合IEEE 754标准的编译平台可以定义一个符号(附录F)。 如果编译器定义了这个符号,那么是的,断言将被保证保持不变。当文字常量可以精确地表示为浮点数时,则必须在编译程序中获得该浮点数 我想不出任何一个非IEEE 754浮点系统没有零,或者没有理由不将源代码中的文字0映射到它。你不是在问0.0是否总是精确表示
double n = 0;
assert(n == 0);
< C++ > C99不强制IEEE75,只推荐它。符合IEEE 754标准的编译平台可以定义一个符号(附录F)。 如果编译器定义了这个符号,那么是的,断言将被保证保持不变。当文字常量可以精确地表示为浮点数时,则必须在编译程序中获得该浮点数
我想不出任何一个非IEEE 754浮点系统没有零,或者没有理由不将源代码中的文字
0
映射到它。你不是在问0.0
是否总是精确表示
在语句assert(n==0)
中,0
在进行比较之前被转换为double
。因此,只有将0
从int
转换为double
不可复制时,才能触发断言。这是一个比你所问的要弱得多的限制,并且几乎肯定会成立(尽管我想不出一个标准参考来保证它在我的头脑中是正确的)
对于您想问的问题:
正如其他人提到的,C标准不要求浮点类型映射到IEEE-754,但我不知道任何C编译器使用的浮点表示法都没有精确的零表示法。也就是说,C实现使用没有精确零的
double
格式是“合法的”。比较将整数提升为double。您要问的是,编译器是否保证在每次将相同的整数转换为double时执行相同的转换。我相信是的
不仅如此,任何足够小的整数都可以用double表示。我无法想象任何编译器会在这种情况下进行不精确的转换。C标准确实对浮点值的表示方式施加了一些限制。在§5.2.4.2.2浮动类型的特征中,浮点数必须表现出由模型定义的特征: x=sbe∑k=1..p fk b-k 其中:
- s为符号,必须为±1李>
- b是基数,必须是大于1的整数李>
- e是指数,必须是介于emin和emax之间的整数李>
- p为精度;及
- fk是非负整数<b——有效位的数字
因此,当从整数0转换为浮点类型时,零必须始终保持不变。因此,断言必须始终成立。如果这不起作用,那么什么会……我想你应该先做一些计算,对吗?在这种情况下,由于舍入误差,计算结果可能与0略有不同。我认为你的代码示例与其说是有用的,不如说是误导性的。琐事:在IEEE 754中,浮点数可以精确地表示高达±2^24的整数,并将其加倍到±2^53。如果不是
n==0
,那么n-n==0
呢?马克缺乏想象力的答案似乎需要你的智慧…;-)移动设备上使用了哪些浮点变量?直到最近,桌面一直是大多数业余/半专业开发人员的主要游乐场,但随着移动设备变得非常流行,它们正在成为主要的开发平台,因此我们需要考虑这些设备上的浮点表示。您对移动设备支持754的信心程度是多少?@Martin:您可能会注意到,我的答案并不取决于IEEE-754的支持。这就是说,iPhone的语义接近754(默认的浮点环境将非规范化刷新为零,但它在其他方面符合)。我相信Android也有大部分的-754算法(继承自Java)。我对其他平台没有把握。然而,我确实相信主流移动设备上使用的所有浮点格式都有一个精确的零表示。不过,这真的只是一个再现性的例子吗?在一种情况下,0
可能被转换为double,但在另一种情况下,它被转换为double,存储在内存中,然后被检索。我认为C和C++实现在存储到内存时降低精度是合法的,不是吗?在这种情况下,在假设的0
没有精确表示的情况下,n
不能因此而不等于(double)0
?或者仅仅是中间的算术结果可以比存储的值具有更高的精度,而不是由强制转换产生的“全新”双倍?或者我想象过整个事情,而在X87上典型的不把中间值变成64位的旧行为,从来没有符合C或C++标准吗?我可以肯定的是,恶意的实现可能有一个没有精确表示零的双类型,根据RTSC的低位在两个最接近的值之间进行选择,并声明符合标准。然而,这确实是邪恶的。有几个问题:对实际文本的狭义解读并不意味着必须有零的表示;相反,它只要求零由零的有效位表示。更重要的是,请特别注意脚注(16):“浮点模型旨在阐明