当前位置: 首页 > 知识库问答 >
问题:

浮点精度是可变的还是不变的?

宋洲
2023-03-14

我不断得到关于浮点数(即浮动长双)是否有一个且只有一个精度值的混合答案,或者具有可以变化的精度值。

一个名为浮点与双精度的主题似乎暗示浮点精度是绝对精度。

然而,另一个被称为浮点和双精度之间的差异的主题说,

一般来说,双精度有15到16位十进制数字

另一位消息人士说,

浮点型变量的精度通常约为7位有效数字

double类型的变量通常具有约16位有效数字的精度

如果我使用的是敏感代码,当我的值不精确时,这些代码很容易被破坏,我不喜欢参考上面的近似值。所以让我们澄清一下。浮点精度是可变的还是不变的,为什么?

共有3个答案

黄丰
2023-03-14

使用其硬件协处理器(最初是8087)的80x86代码提供三个精度级别:32位、64位和80位。这些都非常符合1985年的IEEE-754标准。最近的标准规定了128位格式。浮点格式有24、53、65和113个尾数位,对应于精度的7.22、15.95、19.57和34.02位小数。

公式为尾数位/对数2 10,其中对数基数为3.321928095。

虽然任何特定实现的精度都没有变化,但当浮点值转换为十进制时,可能会出现这种情况。请注意,值0.1没有精确的二进制表示。它是一种重复位模式(0.00011001100…)就像我们习惯于在小数点后0.3333到大约1/3。

许多语言通常不支持80位格式。一些C编译器可能提供长双精度,它使用80位浮点或128位浮点。唉,它也可能使用64位浮点,具体取决于实现。

NPU有80位寄存器,并使用完整的80位结果执行所有操作。在NPU堆栈内计算的代码受益于这种额外的精度。不幸的是,糟糕的代码生成或糟糕的代码编写可能会通过将中间计算存储在32位或64位变量中来截断或舍入它们。

晋弘义
2023-03-14

所有现代计算机都使用二进制浮点算法。这意味着我们有一个二进制尾数,通常单精度为24位,双精度为53位,扩展精度为64位。(扩展精度在x86处理器上可用,但在ARM或其他类型的处理器上不可用。)

24、53和64位尾数意味着对于介于2k和2k1之间的浮点数,下一个较大的数字分别是2k-23、2k-52和2k-63。这就是决议。每个浮点运算的舍入误差最多为该误差的一半。

那么这是如何转化为十进制数的呢?视情况而定。

取k=0和1≤x

如果x仅略小于2k1,且仅略大于10n,则小数位数最高,例如1000≤ x

当然,您可以阅读“每个计算机科学家都应该了解的浮点运算”这篇文章。

宫坚
2023-03-14

精度是固定的,对于双精度来说正好是53个二进制数字(如果我们排除隐式前导1,则为52个)。这大约是15个十进制数字。

OP要求我详细说明为什么恰好有53个二进制数字意味着“大约”15个十进制数字。

为了直观地理解这一点,让我们考虑一种精度较低的浮点格式:我们将使用4位尾数,而不是像双精度数字那样的52位尾数。

因此,每个数字将如下所示:(-1)s×2yyy×1.xxxx(其中s是符号位,yyy是指数,1.xxxx是标准化尾数)。为了立即讨论,我们将只关注尾数,而不是符号或指数。

以下是1.xxxx对于所有xxxx值的外观表(所有舍入都是半到偶数,就像默认浮点舍入模式的工作方式一样):

  xxxx  |  1.xxxx  |  value   |  2dd  |  3dd  
--------+----------+----------+-------+--------
  0000  |  1.0000  |  1.0     |  1.0  |  1.00
  0001  |  1.0001  |  1.0625  |  1.1  |  1.06
  0010  |  1.0010  |  1.125   |  1.1  |  1.12
  0011  |  1.0011  |  1.1875  |  1.2  |  1.19
  0100  |  1.0100  |  1.25    |  1.2  |  1.25
  0101  |  1.0101  |  1.3125  |  1.3  |  1.31
  0110  |  1.0110  |  1.375   |  1.4  |  1.38
  0111  |  1.0111  |  1.4375  |  1.4  |  1.44
  1000  |  1.1000  |  1.5     |  1.5  |  1.50
  1001  |  1.1001  |  1.5625  |  1.6  |  1.56
  1010  |  1.1010  |  1.625   |  1.6  |  1.62
  1011  |  1.1011  |  1.6875  |  1.7  |  1.69
  1100  |  1.1100  |  1.75    |  1.8  |  1.75
  1101  |  1.1101  |  1.8125  |  1.8  |  1.81
  1110  |  1.1110  |  1.875   |  1.9  |  1.88
  1111  |  1.1111  |  1.9375  |  1.9  |  1.94

您说它提供了多少个十进制数字?您可以说2,因为涵盖了两位十进制数字范围内的每个值,尽管不是唯一的;或者您可以说3,它涵盖了所有唯一值,但不涵盖三个十进制数字范围内的所有值。

为了便于论证,我们假设它有两个十进制数字:十进制精度将是那些十进制数字的所有值都可以表示的位数。

好的,那么,如果我们将所有数字减半(因此我们使用yyy)会发生什么?

  xxxx  |  1.xxxx  |  value    |  1dd  |  2dd  
--------+----------+-----------+-------+--------
  0000  |  1.0000  |  0.5      |  0.5  |  0.50
  0001  |  1.0001  |  0.53125  |  0.5  |  0.53
  0010  |  1.0010  |  0.5625   |  0.6  |  0.56
  0011  |  1.0011  |  0.59375  |  0.6  |  0.59
  0100  |  1.0100  |  0.625    |  0.6  |  0.62
  0101  |  1.0101  |  0.65625  |  0.7  |  0.66
  0110  |  1.0110  |  0.6875   |  0.7  |  0.69
  0111  |  1.0111  |  0.71875  |  0.7  |  0.72
  1000  |  1.1000  |  0.75     |  0.8  |  0.75
  1001  |  1.1001  |  0.78125  |  0.8  |  0.78
  1010  |  1.1010  |  0.8125   |  0.8  |  0.81
  1011  |  1.1011  |  0.84375  |  0.8  |  0.84
  1100  |  1.1100  |  0.875    |  0.9  |  0.88
  1101  |  1.1101  |  0.90625  |  0.9  |  0.91
  1110  |  1.1110  |  0.9375   |  0.9  |  0.94
  1111  |  1.1111  |  0.96875  |  1.   |  0.97

按照与之前相同的标准,我们现在处理的是1位小数。因此,您可以看到,根据指数的不同,您可以有更多或更少的十进制数字,因为二进制和十进制浮点数之间没有清晰的映射。

同一个参数适用于双精度浮点数(尾数为52位),只有在这种情况下,根据指数得到15或16位十进制数字。

 类似资料:
  • 用于图像识别的神经网络可真的很大。可以有数千个输入/隐藏的神经元,数百万个连接,这会占用大量的计算机资源。 虽然在C++中float通常是32bit和双64bit,但它们在速度上没有太大的性能差异,但使用float可以节省一些内存。 有了一个神经网络,什么是用sigmoid作为激活函数,如果我们可以选择神经网络中哪些变量可以浮点或双变量可以浮点,以节省内存而不使神经网络无法执行? 而训练/测试数据

  • 问题内容: 我有数千个音频文件,我想使用Keras和Theano对它们进行分类。到目前为止,我为每个音频文件生成了一个28x28的声谱图(可能更大一些,但我现在只是想让算法起作用),然后将图像读入矩阵。因此,最终我得到了这个大图像矩阵,以馈入网络进行图像分类。 在一个教程中,我找到了这个mnist分类代码: 此代码运行,并且我得到预期的结果: 到现在为止,一切都运行良好,但是,当我将上述算法应用于

  • 在我的计算机科学课程中,我们正在研究浮点数以及它们在内存中是如何表示的。我已经理解了它们在内存中是如何表示的(尾数/有效数、指数及其偏差、符号位),我也理解了浮点是如何相互添加和减去的(反规格化和所有那些有趣的东西)。然而,在翻阅一些学习问题时,我注意到一些我无法解释的东西。 当一个不能精确表示的浮点数加到自己身上几次时,答案比我们在数学上预期的要低,但当同一个浮点数乘以一个整数时,答案就精确地得

  • 我编写了一个程序来演示Go中的浮点错误: 它打印: 这与用C编写的相同程序的行为相匹配(使用双代码类型) 但是,如果改用,程序就会陷入无限循环!如果将C程序修改为使用而不是,它将打印 为什么在使用时,Go程序的输出与C程序的输出不一样?

  • 问题内容: 我知道这可能很愚蠢,但是很多地方都声称Java中的Integer类是不可变的,但是下面的代码: 毫无困难地执行(给出预期的结果)6。因此有效地改变了a的值。这不是说Integer是可变的吗?第二个问题和一些小问题:“不变的类不需要复制构造函数”。有人在乎解释原因吗? 问题答案: 不可变并不意味着永远不能等于另一个值。例如,也是不可变的,但是我仍然可以这样做: 并没有改变,而是变成了一个