当前位置:  开发笔记 > 编程语言 > 正文

为什么C没有无符号浮点数?

如何解决《为什么C没有无符号浮点数?》经验,为你挑选了7个好方法。

我知道,这个问题似乎很奇怪.程序员有时会想太多.请继续阅读......

在CI中使用signedunsigned整数很多.我喜欢这样一个事实:如果我执行诸如将有符号整数分配给无符号变量之类的操作,编译器会发出警告.如果我将带符号与无符号整数进行比较,我会得到警告.

我喜欢这些警告.他们帮助我保持我的代码正确.

为什么我们不能为花车提供同样的奢侈品?平方根绝对不会返回负数.还有其他地方负浮动值没有意义.无符号浮点数的完美候选者.

顺便说一句 - 我并不是真的热衷于通过从浮点数中移除符号位来获得的单一额外精度.float因为他们现在对我非常满意.我只想将浮点数标记为无符号,并获得与整数相同的警告.

我不知道任何支持无符号浮点数的编程语言.

知道为什么他们不存在吗?


编辑:

我知道x87 FPU没有处理无符号浮点数的指令.让我们使用带符号的浮点指令.滥用(例如,低于零)可以被认为是未定义的行为,就像未定义有符号整数的溢出一样.



1> Brian R. Bon..:

为什么C++不支持无符号浮点数是因为CPU没有等效的机器代码操作来执行.因此支持它是非常低效的.

如果C++确实支持它,那么你有时会使用unsigned float而没有意识到你的性能刚被杀死.如果C++支持它,则需要检查每个浮点操作以查看它是否已签名.对于执行数百万次浮点运算的程序,这是不可接受的.

所以问题就是为什么硬件实施者不支持它.我认为答案是最初没有定义无符号浮点标准.由于语言喜欢向后兼容,即使添加了语言也无法使用它.要查看浮点规范,您应该查看IEEE标准754浮点数.

您可以通过创建一个封装浮点数或双精度的无符号浮点类并在尝试传入负数时抛出警告来解决没有无符号浮点类型的问题.这样效率较低,但是如果你没有强烈地使用它们,你可能不会关心那种轻微的性能损失.

我肯定看到有一个无符号浮点数的用处.但是C/C++倾向于选择效率最高的安全性.


C/C++不需要特定的机器代码操作来实现该语言.早期的C/C++编译器可以为386生成浮点代码 - 一个没有FPU的CPU!编译器将生成库调用以模拟FPU指令.因此,可以在没有CPU支持的情况下完成ufloat
Skizz,虽然这是正确的,Brian已经解决了这个问题 - 因为没有相同的机器代码,相比之下,性能将会非常糟糕.
@Brian R. Bondy:我在这里失去了你:"因为没有相同的机器代码操作让CPU执行......".你能用更简单的方法解释一下吗?

2> Skizz..:

C/C++中有符号和无符号整数之间存在显着差异:

value >> shift

有符号值保持最高位不变(符号扩展),无符号值清除最高位.

没有无符号浮点数的原因是,如果没有负值,您会很快遇到各种问题.考虑一下:

float a = 2.0f, b = 10.0f, c;
c = a - b;

c有什么价值?-8.但是在没有负数的系统中这意味着什么.FLOAT_MAX - 8也许吧?实际上,这不起作用FLOAT_MAX - 8由于精确效果而是FLOAT_MAX所以事情更加棘手.如果它是更复杂的表达式的一部分怎么办:

float a = 2.0f, b = 10.0f, c = 20.0f, d = 3.14159f, e;
e = (a - b) / d + c;

由于2的补码系统的性质,这不是整数的问题.

还要考虑标准的数学函数:sin,cos和tan只能用于输入值的一半,你找不到值<1的对数,你无法求解二次方程:x =( - b +/- root( bb - 4.ac))/ 2.a,依此类推.事实上,它可能不适用于任何复杂的函数,因为这些函数往往被实现为多项式近似,这将在某处使用负值.

所以,无符号浮点数是没用的.

但这并不意味着一个范围检查浮点值的类是没用的,您可能希望将值钳位到给定范围,例如RGB计算.


“值>>有符号值的移位”不改变最高位(符号扩展)。您确定吗?我认为这是实现定义的行为,至少对于负有符号的值而言。

3> Treb..:

我相信unsigned int的创建是因为需要比signed int提供的更大的值余量.

浮点数具有更大的余量,因此对于无符号浮点数从不存在"物理"需求.正如你在自己的问题中指出的那样,额外的1位精度是无可挽回的.

编辑: 在阅读Brian R. Bondy的答案后,我必须修改我的答案:他绝对是正确的,底层CPU没有无符号浮点运算.但是,我坚持认为这是基于我上述原因的设计决定;-)


此外,整数的加法和减法是相同的有符号或无符号 - 浮点,而不是那么多.鉴于此类功能的边际效用相对较低,谁会做额外的工作来支持有符号和无符号浮点数?

4> ephemient..:

(另外,Perl 6允许你写

subset Nonnegative::Float of Float where { $_ >= 0 };

然后你可以Nonnegative::Float像任何其他类型一样使用.)

对于无符号浮点运算没有硬件支持,因此C不提供它.C主要设计为"便携式组装",即尽可能靠近金属而不被绑定到特定平台.

[编辑]

C就像汇编:你看到的正是你得到的.隐含的"我会检查这个浮动对你来说是非负的"违背了它的设计理念.如果你真的想要它,你可以添加assert(x >= 0)或类似,但你必须明确地这样做.



5> Johannes Sch..:

我认为特雷布走在正确的轨道上.对于具有无符号对应类型的整数,这一点更为重要.那些是用于位移并用于位图的那些.一个标志位刚刚开始.例如,右移一个负值,结果值是在C++中定义的实现.使用无符号整数或溢出这样的整数就可以完美地定义语义,因为在这种情况下没有这样的位.

因此,至少对于整数,需要单独的无符号类型比仅发出警告更强.对于花车,不需要考虑以上所有要点.因此,我认为没有真正需要对它们提供硬件支持,而C此时已经不支持它们了.



6> Tobias Wärre..:

我想这取决于IEEE浮点规范只有签名并且大多数编程语言都使用它们.

关于ieee浮点数的wikipedia articla

编辑:另外,正如其他人所指出的,大多数硬件都不支持非负浮点数,因此正常类型的浮点数更有效,因为有硬件支持.



7> Pete Kirkham..:

平方根一定永远不会返回负数。在其他地方,负浮点值也没有意义。无符号浮动的完美候选人。

C99支持复数和sqrt的类型通用形式,因此sqrt( 1.0 * I)为负数。


评论者强调了上面的一些微妙之处,因为我指的是类型通用sqrt宏而不是函数,它将通过将复数截断为其实数部分来返回标量浮点值:

#include 
#include 

int main () 
{
    complex double a = 1.0 + 1.0 * I;

    double f = sqrt(a);

    return 0;
}

它也包含脑筋,因为任何复数的sqrt的实部是正数或零,并且sqrt(1.0 * I)是sqrt(0.5)+ sqrt(0.5)* I而不是-1.0。


sqrt(i)的结果是一个复数。而且由于复数没有排序,所以不能说复数是负数(即<0)
推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有