为什么C没有unsigned浮点数?
我知道,这个问题似乎很奇怪。 程序员有时会想太多。 请继续阅读…
在CI中使用有符号和无符号整数很多。 我喜欢这样一个事实,即编译器会警告我,如果将某个有符号整数赋值给一个无符号variables。 我收到警告,如果我比较签名与无符号整数和更多。
我喜欢这些警告。 他们帮助我保持我的代码正确。
为什么我们没有同样的花车奢侈品? 平方根绝对不会返回负数。 还有其他的地方,负浮动值没有意义。 完美的候选人一个无符号的浮点数。
顺便说一句 – 我不是真的热衷于我可以通过从浮标移除符号标志获得一个额外的精度。 我现在对float
很满意。 我只想把浮点数标记为unsigned,得到与整数相同的警告。
我不知道任何支持无符号浮点数的编程语言。
任何想法,为什么他们不存在?
编辑:我知道x87 FPU有没有处理未签名的浮动指令。 让我们只使用签署的浮动指令。 误用(例如,低于零)可能被认为是未定义的行为,就像未定义有符号整数的溢出一样。
为什么C ++不支持未签名的浮点数是因为CPU没有执行等效的机器代码操作。 所以支持它是非常低效的。
如果C ++确实支持它,那么你有时候会使用一个无符号的float,而没有意识到你的性能已经被杀死了。 如果C ++支持它,那么每个浮点操作都需要被检查,看它是否被签名。 而对于执行数百万次浮点运算的程序,这是不可接受的。
所以问题是为什么硬件实施者不支持它。 我认为答案就是最初没有定义无符号浮点标准。 由于语言是向后兼容的,即使它被添加语言也无法使用它。 要查看浮点规格,您应该查看IEEE标准754浮点型 。
你可以通过创build一个无符号的浮点类来封装一个浮点types或者双精度浮点types,如果你尝试传递一个负数,你可以避开无符号浮点types。 这效率不高,但是如果你不使用它们,你可能不会在意这种轻微的性能损失。
我绝对看到有一个无符号浮点数的有用性。 但C / C ++倾向于select最适合每个人的安全性的效率。
(另外,Perl 6可以让你编写
subset Nonnegative::Float of Float where { $_ >= 0 };
然后你可以像使用其他types一样使用Nonnegative::Float
。)
没有硬件支持无符号浮点运算,所以C不提供它。 C的devise大多是“便携式组装”,也就是说,尽可能靠近金属,而不必拘泥于特定的平台。
[编辑]
C就像大会一样:你看到的正是你所得到的。 一个隐含的“我会检查这个浮点数对你来说是非负的”违背了它的devise哲学。 如果你真的想要它,你可以添加assert(x >= 0)
或类似的,但你必须明确这样做。
在C / C ++中有符号和无符号整数有显着的区别:
value >> shift
带符号的值保持最高位不变(符号扩展),无符号值清除最高位。
没有unsigned float的原因是如果没有负值,你很快就会遇到各种各样的问题。 考虑这个:
float a = 2.0f, b = 10.0f, c; c = a - b;
c有什么价值? -8。 但是在没有负数的系统中这意味着什么。 FLOAT_MAX – 8也许? 实际上,由于精确度的影响,FLOAT_MAX – 8不能起到FLOAT_MAX的作用,所以事情更加棘手。 如果它是更复杂的expression的一部分呢?
float a = 2.0f, b = 10.0f, c = 20.0f, d = 3.14159f, e; e = (a - b) / d + c;
由于2的补码系统的性质,这对整数不是问题。
还要考虑标准的math函数:sin,cos和tan只能用于他们input值的一半,你找不到值的对数<1,你不能求解二次方程:x =(-b +/- root bb – 4.ac))/ 2.a等等。 事实上,它可能不适用于任何复杂的函数,因为这些函数往往被实现为多项式近似值,这些近似值将在某个地方使用负值。
所以,未签名的浮点数是无用的。
但是,这并不意味着说范围检查浮点值的类没有用,您可能想要将值限制在给定的范围内,例如RGB计算。
我相信unsigned int是由于需要比签名的int可以提供的更大的值边缘而创build的。
一个浮点数有一个更大的余量,所以从来没有一个“物理”需要一个无符号的浮点数。 当你在你的问题中指出你自己,额外的1位精度是没有什么可以杀死的。
编辑:在阅读由布赖恩·R·邦迪的答案后,我不得不修改我的答案:他是绝对正确的底层的CPU没有无符号的浮动操作。 不过,我坚持认为这是基于上述原因的devise决定;-)
我认为Treb是正确的。 对于整数来说,你有一个无符号的对应types更重要。 这些是用于位移和位图使用的 。 一个标志位刚刚进入方式。 例如,右移一个负值,结果值就是在C ++中定义的实现。 用一个无符号整数或者溢出这样的方式来完成定义的语义,因为没有这样的位。
所以对于整数来说,至less需要一个单独的无符号types,而不仅仅是给出警告。 上述所有的点都不需要考虑浮动。 因此,我认为没有必要为它们提供硬件支持,而C在这一点上已经不支持它们了。
我想这取决于IEEE浮点规范只是签名,大多数编程语言使用它们。
维基百科关于ieee浮点数的说法
编辑:另外,正如别人所指出的,大多数硬件不支持非负浮点数,所以正常types的浮点数更有效率,因为有硬件支持。
平方根绝对不会返回负数。 还有其他的地方,负浮动值没有意义。 完美的候选人一个无符号的浮点数。
C99支持复数,以及一个sqrttypes的通用forms,所以sqrt( 1.0 * I)
将是负数。
注释者在上面突出显示了一点光泽,因为我指的是typesgenericssqrt
macros而不是函数,它将通过复合体的截断将其返回到标量浮点值:
#include <complex.h> #include <tgmath.h> 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。
我认为主要的原因是未签名的浮点数与未经签名的inttypes相比将会有非常有限的用处。 我不认为这是因为硬件不支持它。 以前的处理器根本没有浮点function,都是用软件模拟的。 如果未签名的浮点数是有用的,那么它们将首先在软件中实现,而硬件也将随之而来。
C中的无符号整数types被定义为服从抽象代数环的规则。 例如,对于任何值X和Y,将XY添加到Y将产生X.无符号整数types在所有情况下都保证遵守这些规则,而不涉及到任何其他数值types[或无符号不同大小的types]而这种保证是这种types最重要的特征之一。 在某些情况下,放弃表示负数的能力是值得的,只有无符号types才能提供额外的保证。 浮点types,无论是否有符号,都不能遵守代数环的所有规则[例如,它们不能保证X + YY等于X],事实上IEEE甚至不允许它们遵守一个规则等价类[通过要求某些值比较不等于自己]。 我不认为一个“无符号”的浮点types可以遵循普通浮点types所不能的任何公理,所以我不确定它会提供什么优点。
我怀疑这是因为C编译器所针对的底层处理器没有处理无符号浮点数的好方法。