c++ 浮点与定点:利/弊是什么?

huwehgph  于 2023-08-09  发布在  其他
关注(0)|答案(8)|浏览(138)

浮点类型通过将其有效位和指数分别存储在单独的二进制字上来表示数字,因此它适合16,32,64或128位。
定点类型存储两个字的数字,一个表示整数部分,另一个表示基数之后的部分,以负指数2^-1、2^-2、2^-3等表示。
浮点数更好,因为它们在指数意义上具有更宽的范围,但如果想要在某个范围内以更高的精度存储数字,则不是这样,例如仅使用从-16到16的整数,因此使用更多的位来保存基数之后的数字。
在性能方面,哪一个具有最好的性能,或者是否存在一些比另一个更快的情况?
在视频游戏编程中,每个人都使用浮点是因为FPU使它更快,还是因为性能下降微不足道,还是他们自己制作固定类型?
为什么C/C++中没有固定类型?

5lhxktic

5lhxktic1#

该定义涵盖了非常有限的定点实现子集。
更正确的说法是,在固定点中仅存储尾数,并且指数是先验确定的常数。没有要求二进制点落在尾数内,并且绝对没有要求它落在单词边界上。例如,以下所有都是“固定点”:

  • 64位尾数,比例为2-32(这符合问题中列出的定义)
  • 64位尾数,比例为2-33(现在整数和小数部分不能由八位字节边界分隔)
  • 32位尾数,按24缩放(现在没有小数部分)
  • 32位尾数,缩放2-40(现在没有整数部分)

GPU倾向于使用没有整数部分的定点(通常是32位尾数按2-32缩放)。因此,OpenGL和Direct 3D等API通常使用能够保存这些值的浮点类型。然而,操作整数尾数通常更有效,因此这些API也允许以这种方式指定坐标(在纹理空间、颜色空间等中)。
至于你声称C没有定点类型,我不同意。C中的所有整数类型都是定点类型。指数通常被假定为零,但这不是必需的,我用C++实现了相当多的定点DSP代码。

rhfm7lfc

rhfm7lfc2#

在代码级,定点算术只是带有隐含分母的整数算术。
对于许多简单的算术运算,定点运算和整数运算本质上是相同的。然而,存在一些运算,其中中间值必须用更高数量的位来表示,然后四舍五入。例如,要将两个16位定点数相乘,结果必须在重新归一化(或饱和)回16位定点之前临时存储在32位中。
当软件不利用矢量化(如基于CPU的SIMD或GPGPU)时,整数和定点算术比FPU更快。当使用向量化时,向量化的效率更重要,使得定点和浮点之间的性能差异是无意义的。
一些架构为某些数学函数提供硬件实现,例如sincosatansqrt,仅用于浮点类型。一些架构根本不提供任何硬件实现。在这两种情况下,专门的数学软件库可以通过仅使用整数或定点算术来提供这些函数。通常,这样的库将提供多个精度水平,例如,仅精确到N位精度的答案,其小于表示的全精度。有限精度版本可能比最高精度版本更快。

yr9zkbsy

yr9zkbsy3#

不动点广泛应用于DSP和嵌入式系统中,其中目标处理器通常没有FPU,并且使用整数ALU可以合理有效地实现不动点。
就性能而言,这可能会根据目标体系结构和应用程序而变化。显然,如果没有FPU,那么定点将快得多。当你有一个FPU时,它也将取决于应用程序。例如,执行一些函数(如sqrt()或log())在指令集中直接支持时将比在算法上实现快得多。
C或C中没有内置的定点类型,我想是因为它们(或至少是C)被设想为系统级语言,并且定点的需求在某种程度上是特定于领域的,也可能是因为在通用处理器上通常没有直接的硬件支持定点。
在C
中,定义一个定点数据类型类,并使用适当的运算符重载和相关的数学函数,可以很容易地克服这个缺点。然而,这个问题有好的和坏的解决方案。一个很好的例子可以在这里找到:http://www.drdobbs.com/cpp/207000448。该文章中代码的链接已断开,但我追踪到了ftp://66.77.27.238/sourcecode/ddj/2008/0804.zip

uqdfh47h

uqdfh47h4#

在此上下文中讨论“精确度”时需要小心。
对于表示中的相同数量的位,最大定点值具有比任何浮点值 * 更多 * 的有效位(因为浮点格式必须将一些位给予指数),但是最小定点值具有比任何非非规范化浮点值 * 更少 * 的有效位(因为定点值在前导零中浪费了其尾数的大部分)。
此外,取决于您划分定点数的方式,浮点值可能能够表示 * 更小 * 的数字,这意味着它具有“微小但非零”的更精确表示。
诸如此类。

bqf10yzr

bqf10yzr5#

浮点数和整数运算之间的区别取决于你心目中的CPU。在英特尔芯片上,时钟信号的差异并不大。整数运算仍然更快,因为有多个整数ALU可以并行工作。编译器也聪明地使用特殊的地址计算指令来优化单个指令中的加法/乘法。转换也是一种操作,所以只要选择你的类型并坚持下去。
在C++中,你可以为定点数学构建自己的类型。你只需要用一个int定义为struct,然后覆盖适当的重载,让它们做它们通常做的事情,再加上一个shift,把逗号放回正确的位置。

drnojrws

drnojrws6#

你在游戏中不使用浮点数,因为它更快或更慢,你使用它是因为浮点数比定点数更容易实现算法。你假设原因与计算速度有关,但这不是原因,它与编程的容易性有关。
例如,您可以将屏幕/视口的宽度定义为从0.0到1.0,屏幕的高度为0.0到1.0。单词的深度为0.0到1.0。等等。矩阵数学,等等使事情真实的容易实现。这样做所有的数学运算,直到你需要在一个真实的屏幕尺寸上计算真实的像素,比如800 x400。将光线从眼睛投射到世界中物体上的点,并使用0到1的数学计算它穿透屏幕的位置,然后将x乘以800,y乘以400并放置该像素。
浮点数不分别存储指数和尾数,尾数是一个愚蠢的数字,在指数和符号之后剩下的是23位,而不是16或32或64位。
浮点数学在其核心使用定点逻辑,需要额外的逻辑和额外的步骤。根据定义,苹果与苹果相比,定点数学更便宜,因为你不必在进入alu的路上操纵数据,也不必在离开的路上操纵数据(正常化)。当您添加IEEE及其所有垃圾时,会添加更多逻辑,更多时钟周期等。(正确签名的无穷大、安静和信号NAN,如果启用了异常处理程序,则相同操作的结果不同)。正如有人在评论中指出的那样,在一个真实的系统中,你可以并行地执行固定和浮动,你可以利用一些或所有的处理器,并以这种方式恢复一些时钟。浮动和固定时钟速率都可以通过使用大量的芯片真实的面积来增加,固定时钟速率将保持更便宜,但是浮动可以使用这些种类的技巧以及并行操作来接近固定速度。

6tqwzwtp

6tqwzwtp7#

一个没有涉及的问题是答案是功耗。虽然它高度依赖于特定的硬件架构,但通常FPU在CPU中消耗的能量比ALU多得多,因此如果您的目标是功耗很重要的移动的应用程序,则值得考虑该算法的定点实现。

t98cgbkg

t98cgbkg8#

这取决于你在做什么。如果你使用固定点,那么你失去精度;你必须选择小数位后的位数(这可能并不总是足够好)。在浮点数中,你不需要担心这个,因为它提供的精度几乎总是足够好,可以完成手头的任务--使用标准形式的实现来表示数字。
优点和缺点归结为速度和资源。在现代的32位和64位平台上,真的不需要使用定点。大多数系统都配有内置FPU,这些FPU是硬连线的,可针对定点操作进行优化。此外,大多数现代CPU内部函数都带有SIMD集等操作,这些操作有助于通过向量化和展开来优化基于向量的方法。所以固定点只会带来负面影响。
在嵌入式系统和小型微控制器(8位和16位)上,您可能没有FPU或扩展指令集。在这种情况下,您可能会被迫使用定点方法或速度不是很快的有限浮点指令集。所以在这些情况下,固定点将是一个更好的-甚至是你唯一的-选择。

相关问题