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

可以转换为二进制并返回十进制而不损失意义的最高有效十进制数字精度是6还是7.225?

刘绍晖
2023-03-14

我遇到过两种不同的浮点数精度公式。

⌊(N-1) 对数10(2)⌋ = 6 个十进制数字(一精度)

N log10(2)・7.225位十进制数字(单精度)

其中 N = 24 有效位(单精度)

第一个公式位于W.Kahan教授编写的“二进制浮点运算IEEE标准754”第4页顶部。

第二个公式可以在Wikipedia文章“单精度浮点格式”中的IEEE 754单精度二进制浮点格式部分找到:binary32。

对于第一个公式,W. Kahan教授说

如果是最多6个sig的十进制字符串。dec.转换为Single,然后再转换回相同的sig数。12月,则最后一个字符串应与原始字符串匹配。

对于第二个公式,维基百科说

...总精度为 24 位(相当于对数10(224)≈ 7.225 位十进制数字)。

这两个公式(6 和 7.225 十进制数字)的结果不同,我期望它们是相同的,因为我假设它们都意味着表示最重要的十进制数字,这些数字可以转换为浮点二进制,然后用与开始时相同数量的有效十进制数字转换回十进制。

为什么这两个数字不同?可以转换为二进制并返回到十进制而不丢失意义的最重要的十进制数字精度是多少?

共有3个答案

袁运良
2023-03-14

请记住,它们是完全相同的公式。记住你的高中数学书身份:

    Log(x^y) == y * Log(x)

它有助于使用计算器实际计算N=24的值:

  Kahan's:      23 * Log(2) = 6.924
  Wikipedia's:   Log(2^24)  = 7.225

卡汉被迫将6.924截断为6位数字,因为地板(),令人沮丧。唯一的实际区别是卡汉少用了1位精度。

很难猜到为什么,教授可能依赖于旧的笔记。写在IEEE-754之前,没有考虑到第24位精度是免费的。该格式使用了一个技巧,浮点值中非 0 的最常见位始终为 1。所以它不需要存储。处理器在执行计算之前将其添加回去。将 23 位存储精度转换为 24 位有效精度。

或者他考虑到从十进制字符串到二进制浮点值的转换本身会产生错误。许多漂亮的圆形十进制值,如0.1,不能完美转换为二进制。它有无穷无尽的数字,就像十进制中的1/3一样。然而,这会产生一个0.5位 /-的结果,通过简单的舍入来实现。所以结果精确到23.5*Log(2)=7.074个十进制数字。如果他假设转换程序很笨拙,没有正确舍入,那么结果可以偏离 /-1位,N-1是合适的。他们并不笨拙。

或者,他像一个典型的科学家或会计师(但愿不会如此)一样思考,并希望将计算结果转换回十进制。例如,当你漫不经心地寻找一个7位数的十进制数,它的来回转换不会产生相同的数。是的,这会增加另一个/- 0.5位误差,总计1位误差。

但是,永远不要犯这种错误,你必须在计算中包含任何因操纵数字而产生的错误。其中一些数字丢失得很快,特别是减法非常危险。

颛孙轩昂
2023-03-14

可以转换成二进制或转换回十进制而不损失有效性的最高有效十进制数字精度是多少?

可以转换为二进制或转换回十进制而不损失有效性的最高有效十进制数字精度(对于单精度浮点数或24位)是6位十进制数字。

为什么这两个数字不同...

数字6和7.225是不同的,因为它们定义了两个不同的东西。6是可以往返的最大十进制数字。7.225是24位二进制整数的近似十进制位数精度,因为24位二进制整数根据其特定值可以有7或8个十进制位数。

7.225是使用特定的二进制整数公式得出的。

d规格 = b·log10(2)

但是,您通常需要知道的是 b 位整数的最小和最大十进制数字。以下公式用于查找特定二进制整数的最小和最大十进制数字(对于 24 位分别为 7 和 8)。

d分钟=⌈(b-1)·log10(2)⌉

dmax=b·log10(2)

要了解有关如何派生这些公式的更多信息,请阅读Rick Regan撰写的二进制整数中的十进制位数。

这一切都很好,但您可能会问,如果您说24位数字的十进制位数范围是7到8,为什么6是往返转换的最大十进制位数?

答案是 - 因为上面的公式只适用于整数,而不适用于浮点数!

每个十进制整数都有一个二进制的精确值。但是,对于每个十进制浮点数,情况并非如此。以 .1 为例。二进制中的 .1 是数字 0.000110011001100...,它是重复或重复的二进制文件。这会产生舍入误差。

此外,表示十进制浮点数比表示同等意义的十进制整数多花了一位。这是因为浮点数越接近0就越精确,离0越远越不精确。正因为如此,许多接近最小值和最大值范围的浮点数(emin=-126和emax=127对于单精度)由于舍入误差而失去1位精度。要直观地看到这一点,请查看Josh Haberman编写的每个计算机程序员都应该了解的关于浮点数的知识,第1部分。

此外,至少有784,757正七位数的十进制数在往返转换后不能保留其原始值。这种数在往返转换后不能存活的一个例子是8.589973e9。这是不保留其原始值的最小正数。

这是您应该用于浮点数精度的公式,它将为您提供6位十进制数字进行往返转换。

d最大值 = ⌊(b-1)·日志10(2)⌋

要进一步了解这个公式是如何推导出来的,请阅读同样由Rick Regan撰写的往返转换所需的位数。Rick做了出色的工作,通过引用严格的证明展示了公式推导。

因此,您可以建设性地利用上述公式;如果您了解它们是如何工作的,您可以将它们应用于任何使用浮点数据类型的编程语言。您所要知道的只是您的浮点数据类型具有的有效位的数量,并且您可以找到它们各自的十进制位数,您可以指望它们在往返转换后不会失去意义。

2017年6月18日更新:我想包含一个链接到Rick Regan的新文章,这篇文章更详细,在我看来,比这里提供的任何答案都更好地回答了这个问题。他的文章是“二进制浮点数的十进制精度”,可以在他的网站www.exploringbinary.com上找到。

范玄裳
2023-03-14

这是在谈论两件略有不同的事情。

7.2251 位数字是在内部存储数字的精度。例如,如果您使用双精度数字进行计算(因此您从大约15位精度开始),然后将其舍入为单精度数字,则此时剩余的精度约为7位。

6 位数字是在谈论可以通过往返转换从一串十进制数字到浮点数,然后回到另一串十进制数字来保持的精度。

因此,假设我以一个像< code>1.23456789这样的数字作为字符串开始,然后将其转换为float32,再将结果转换回字符串。当我这样做了,我可以期待6位数完全匹配。第七个数字可能是四舍五入的,所以我不一定期望它匹配(虽然它可能是原字符串的/- 1。

例如,考虑以下代码:

#include <iostream>
#include <iomanip>

int main() {
    double init = 987.23456789;
    for (int i = 0; i < 100; i++) {
        float f = init + i / 100.0;
        std::cout << std::setprecision(10) << std::setw(20) << f;
    }
}

这将生成如下所示的表:

     987.2345581         987.2445679         987.2545776         987.2645874
     987.2745972         987.2845459         987.2945557         987.3045654
     987.3145752          987.324585         987.3345947         987.3445435
     987.3545532          987.364563         987.3745728         987.3845825
     987.3945923          987.404541         987.4145508         987.4245605
     987.4345703         987.4445801         987.4545898         987.4645386
     987.4745483         987.4845581         987.4945679         987.5045776
     987.5145874         987.5245972         987.5345459         987.5445557
     987.5545654         987.5645752          987.574585         987.5845947
     987.5945435         987.6045532          987.614563         987.6245728
     987.6345825         987.6445923          987.654541         987.6645508
     987.6745605         987.6845703         987.6945801         987.7045898
     987.7145386         987.7245483         987.7345581         987.7445679
     987.7545776         987.7645874         987.7745972         987.7845459
     987.7945557         987.8045654         987.8145752          987.824585
     987.8345947         987.8445435         987.8545532          987.864563
     987.8745728         987.8845825         987.8945923          987.904541
     987.9145508         987.9245605         987.9345703         987.9445801
     987.9545898         987.9645386         987.9745483         987.9845581
     987.9945679         988.0045776         988.0145874         988.0245972
     988.0345459         988.0445557         988.0545654         988.0645752
      988.074585         988.0845947         988.0945435         988.1045532
      988.114563         988.1245728         988.1345825         988.1445923
      988.154541         988.1645508         988.1745605         988.1845703
     988.1945801         988.2045898         988.2145386         988.2245483

如果我们仔细研究一下,我们可以看到前六位有效数字总是精确地遵循模式(即,每个结果恰好比其前身大0.01)。正如我们在原始Double中看到的,该值实际上是98x.xx456-但是当我们将单精度浮点数转换为十进制数时,我们可以看到7th数字经常不会被正确地读回-因为后续数字大于5,它应该向上舍入到98x.xx46,但是一些值不会(例如,第一列中倒数第二个项目是988.154541,它将向下舍入而不是向上舍入,因此我们最终会得到98x.xx45而不是46。因此,即使(存储的)值精确到7位(加上一点点),当我们通过转换到十进制和返回来往返该值时,我们不能再依赖第七位精确匹配了(即使有足够的精度,它会经常出现)。

1。这基本上意味着7位数,第8位位数比没有要精确一些,但不是一整位数。例如,如果我们从1.2345678的双精度转换为。225位精度数字意味着最后一个数字大约是从那里开始的数字的/-.775(而如果没有225位精确度数字,则基本上是从那里出发的数字的--1)

 类似资料:
  • 我想知道如何将舞蹈方法的十进制结果包含到灯光方法中。例如,在这个程序中,如果我输入5F,十进制结果将是95。我希望95在light方法中显示为静态int变量,以便转换为二进制数。如果你能告诉我如何将十六进制数限制在2位数以内,那也会很有帮助。感谢阅读! } }

  • 我可以运行这个程序,但由于某些原因,它会显示/放置随机字符,而不是二进制的初始值,而且我似乎无法将程序从十进制运行回二进制。我该如何改进这些代码。要明确说明它不会将二进制转换为十进制,我将如何将其转换回十进制转换为二进制,如果有一些代码可以帮助我,将不胜感激。

  • 本文向大家介绍十进制到二进制转换,包括了十进制到二进制转换的使用技巧和注意事项,需要的朋友参考一下 十进制数字也可以转换为二进制格式。要将十进制数转换为二进制数,我们需要将数字除以2,直到达到0或1。然后,在每一步骤中,其余部分将分开存储以形成相反的二进制等效数。 在此算法中,我们将遵循递归方法。这将帮助我们在不使用堆栈数据结构的情况下解决问题。在实现中,我们知道函数的递归将遵循内部堆栈。我们将使

  • Python3 实例 以下代码用于实现十进制转二进制、八进制、十六进制: # -*- coding: UTF-8 -*- # Filename : test.py # author by : www.runoob.com # 获取用户输入十进制数 dec = int(input("输入数字:")) print("十进制数为:", dec) print("转换为二进制为:", bin(dec

  • 我正在尝试将数字从十进制值转换为其IEEE 752形式。例如: 我写了这个方法: 有个问题我解决不了,我再举个例子说清楚。 但是当数字为负数时,例如 我收到以下错误: 这意味着我的代码可以完美地处理正数(包括零),但如果是负数,代码就会崩溃。问题出在哪里? 笔记 我想我可以用这种方式解决我的问题 检查是否有一个字符At(0)等于1 如果是(numero.charAt(0)==1),则删除第一个字符

  • 本文向大家介绍科学知识:二进制、八进制、十进制、十六进制转换,包括了科学知识:二进制、八进制、十进制、十六进制转换的使用技巧和注意事项,需要的朋友参考一下 一、 十进制与二进制之间的转换 (1) 十进制转换为二进制,分为整数部分和小数部分 ① 整数部分 方法:除2取余,逆序排列,即每次将整数部分除以2,余数为该位权上的数,而商继续除以2,余数又为上一个位权上的数,这个步骤一直持续下去,直到商为0为