精华内容
下载资源
问答
  • 浮点数的有效数字位数

    千次阅读 多人点赞 2019-01-28 01:49:54
    过去有一种很普遍的说法是单精度浮点数的有效数字是6到7位。...如果一个数字用10进制表示时有效数字位数大于等于7位,那么用单精度浮点数记录的话,能确保至少正确记录前7位。 为什么说“至少”?比如,...

    过去有一种很普遍的说法是单精度浮点数的有效数字是6到7位。同时也有一个很普遍的问题就是:“6到7位是什么意思?到底是6位还是7位?”。现在似乎主流认知已经变成了单精度浮点数的有效数字就是7位。事实究竟是怎么样的?

    先说结论

    单精度浮点数可以保证7位10进制有效数字。如果一个数字用10进制表示时有效数字位数大于等于7位,那么用单精度浮点数记录的话,能确保至少正确记录前7位
    为什么说“至少”?比如,4294967296有10位10进制有效数字,但只有1位2进制有效数字(2进制表示是1后面32个0)。我们可以验证单精度浮点数是可以正确记录所有10位有效数字的。但上面只是特殊情况,对于随便给出的一个数,只有第7位和之前的有效数字是能确信正确的。

    凭什么说就是7位,为什么不是6位、8位?

    最简单的2进制的情况

    首先,我假设我们知道一个单精度浮点数种有24位2进制的有效数字(不知道的同学,请先自行搜索IEEE 754)。很显然,对于有24位或者以上2进制有效数字的数,单精度浮点数能保证前24位。

    再看看16进制

    我们知道16进制的1位对应2进制的4位(不知道的同学,……姑且4位2进制数刚好有16种不同的情况)。2进制的24位刚好对应16进制的6位,也就是能保证6位16进制的有效数字。
    但是假设我们只有23位2进制有效数字的话,那么我们就只能保证5位了。

    接下来我们更具体地看一下。假设有16进制数87654321(16)87654321_{(16)},我们可以写成8.7654321(16)×1678.7654321_{(16)} \times 16^7。2进制的话,可以写成1000.0111011001010100001100100001(2)×2281000.0111'0110'0101'0100'0011'0010'0001_{(2)} \times 2^{28}如果我们只有24位2进制有效数字,则后面一部分有效数字无法记录,就成了1000.01110110010101000011(2)×2281000.0111'0110'0101'0100'0011_{(2)} \times 2^{28}也就是8.76543(16)×1678.76543_{(16)} \times 16^7。如果再减少1位2进制有效数字的话1000.0111011001010100001(2)×2281000.0111'0110'0101'0100'001_{(2)} \times 2^{28}我们将只有3位2进制数001能用来表示最后1位16进制有效数字。我们知道,3位2进制数只有8种不同情况,无法区分16进制1位数的16种情况。更具体地,比如这样我们无法区分8.76543(16)×1678.76543_{(16)} \times 16^78.76542(16)×1678.76542_{(16)} \times 16^7,因为它们的最后一位都会被表示成001。

    可以看到,无法保证有效数字的某一位,意味着我们没办法区分这一位可能出现的所有情况。反过来,如果说我们能保证某一位,说明去掉这一位之前所用掉的2进制有效数字位数后,我们还能剩下足够的2进制位数来区分这一位可能出现的所有情况

    回过头看前面我们用1位2进制表示10位10进制有效数字的情况。1位2进制有效数字有可能表示出10位的10进制有效数字,但是要能区分出10位10进制数的所有情况,我们还是需要更多的2进制位。

    万恶的10进制

    如果能见到神的话,我一定要问他人为什么要长10个指头而不是8个——如果不能是16个的话……

    下面我们要解决的问题是:去掉10进制某一位之前用掉的2进制有效数字后,我们怎么计算还剩下多少2进制位数。

    高能预警:这将不是个整数

    我们知道3位2进制数有8种不同情况,4位2进制数有16种不同情况。而每位有10种情况的10进制要对应2进制的多少位?咱们姑且直接用这结果log2103.322log_210 \approx 3.322对于单精度浮点数,第N位10进制有效数字后还有24N×log21024 - N \times log_210个2进制位可用。如果说单精度浮点数能保证N位有效数字,意味着N位后刚好不再有足够的2进制位数能区分10种不同情况。可以很容看出,这个N应该是让N×log210N \times log_210不大于24的最大的整数。也就是N=24log210=7N = \lfloor {24 \over log_210} \rfloor = 7最终,我们得出N是7。(x\lfloor x \rfloor表示对xx向下取整)

    至此为止,我们知道了该如何计算有限位数的2进制有效数字能保证的10进制有效数字位数。比如我们还可以计算53位2进制有效数字的双精度浮点数可以保证的10进制位数是53log210=15\lfloor {53 \over log_210} \rfloor = 15

    正篇到此结束。

    后记

    这里开始,我不再保证能尽量说人话。

    换个角度

    因为有Mlog210=log22Mlog210=log102M{M \over log_210} = {log_22^M \over log_210} = log_{10}2^M所以单精度浮点能保证的有效数字位数等价于2242^{24}(也就是16777216)去掉最高位后的位数。很多人会说这个就是单精度浮点数能表示7位有效数字的原因。从这个角度解释也是可以的,但是直接这么下结论跳过的步骤太多了。而且从这角度解释铺垫起来会麻烦很多。

    “至少”的问题

    为了方便,我们看16进制。

    这个问题用24位有效数字不太好说,我们看23位。上面说了2进制23位是可以确保16进制的5位的。但是1.2345678(16)×167=1.0010001101000101011001111000(2)×2281.2345678_{(16)} \times 16^7 = 1.0010'0011'0100'0101'0110'0111'1000_{(2)} \times 2^{28}保留23位有效数字是1.0010001101000101011001(2)×228=1.234564×1671.0010'0011'0100'0101'0110'01_{(2)} \times 2^{28} = 1.234564 \times 16^7好像出来了6位。应该很容易注意到,这里16进制的最高位只占用了2进制的1位,所以后面多了3位可用。

    所以计算第N位还能使用的2进制位数,不是简单的用总的2进制位数,减去(N1)×4(N - 1) \times 4。而应该是减去第1位使用的2进制位数后,再减(N2)×4(N - 2) \times 4

    你可能觉得这样我们前面的方法就不准确的了,其实不然。因为我们要计算的是位数最少的情况,而这样只会让位数变多。

    除了最开始提到的特殊情况,这是单精度浮点数正确表示超过7位10进制有效数字的更普遍的一种特殊情况。当然,这样最多只能表示出8位。

    非整数的位数是什么鬼

    拿10进制来讲,我们可以说第N位和10N10^N是对应的。比如我们想把3往左移动2位,就可以3×102=3003 \times 10^2 = 300。于是往左移动半位也就是3×100.5=3109.4873 \times 10^{0.5} = 3 \sqrt {10} \approx 9.487
    前面10进制1位对应2进制log2103.322log_210 \approx 3.322。很显然2log210=102^{log_210} = 10

    展开全文
  • 浮点数有效数字位数

    千次阅读 2012-05-25 22:27:17
    所以这里我们可以得到float的十进制表示有效数字个数为: 这里最小的n为7,对于double,最小的n为15。 有时我们在代码中可能会看到比较浮点数时,会使用一个epsilon,而这个epsilon = 1e-6,可能就是因为当...

    在上一篇《浮点数能够精确表示的整数的范围》中,我们知道了,对于float,实际有效的尾数是23位,对于double,实际有效的位数是53位。所以这里我们可以得到float的十进制表示有效数字个数为:


    这里最小的n为7,对于double,最小的n为15。

    有时我们在代码中可能会看到比较浮点数时,会使用一个epsilon,而这个epsilon = 1e-6,可能就是因为当浮点数绝对值 >= 1时,小数点后有效位数为6位。


    EDIT:  (2012/7/7)

    上面的说法可能有些有些模糊,这里我再试图说明一下。

    对于IEEE754格式,具体的尾数的有效数字个数分2种,一种是规格化数的情况,另一种是非规格化数的情况。非规格化数的尾数的有效位数是23,而规格化数多一位,是24。对于绝对值>=1的数,是由规格化数来表示的,也就是这里由24位,那么实际的十进制有效位数就是8。当然绝对值<1的数,也可能是由规格化数来表示,所以此时小数点后应该最多是8位。


    Reference:

    http://en.wikipedia.org/wiki/Floating_point

    展开全文
  • 对一个浮点型数字保留两位小数并输出: #include #include ...这里要注意,单独用setprecision(2)是保留两位有效数字,会输出1.2e+002 也可以在字符串中进行保留小数位的操作 #include #inclu

    对一个浮点型数字保留两位小数并输出:

    #include <iomanip>
    #include<iostream>
    using namespace std;
    int main(){
    float a = 123.666;
    cout<<setiosflags(ios::fixed)<<setprecision(2)<<a;
    }

    输出结果是123.67
    这里要注意,单独用setprecision(2)是保留两位有效数字,会输出1.2e+002

    也可以在字符串中进行保留小数位的操作

    #include<sstream>
    #include <iomanip>
    #include<iostream>
    using namespace std;
    int main(){
    ostringstream oss;
    float a=123.666;
    oss<<setiosflags(ios::fixed)<<setprecision(2)<<a<<endl;
    string s=oss.str();
    cout<<s;}

    输出结果是123.67
    这种方法可用于字符串添加多次保留一定小数位的浮点型数。
    这里还要注意,

    setiosflags(ios::fixed)<<setprecision(2)

    对后续所有输出都起作用,而不是仅对后一个对象起作用。

    展开全文
  • C++输出有效数字位数

    2015-02-05 16:11:14
    cout.setf(ios::fixed); 例子: #include #define PI 3.14159265358979323 using namespace std; int main() { int r; cin>>r; double s; s = r*r*PI; cout.precision(7); cout;
    <span style="font-size:18px;">cout.setf(ios::fixed);</span>

    例子:

    #include <iostream>
    
    #define PI 3.14159265358979323
    using namespace std;
    int main()
    {
        int r;
        cin>>r;
        double s;
        s = r*r*PI;
        cout.precision(7);
        cout<<s<<endl;
    
        return 0;
    }
    
    输入:4

    输出:50.26548

    展开全文
  • 小数点位数roundround(x, n) # x为数字、n为保留的位置 示例> x=3.1415926 > round(x,3) [1] 3.14如果位数太长,需要科学计数...[1] 0有效数字倍数signifsignif(y, n) # y为数字、n为保留的位置 示例> y=0.000000000
  • setprecision(n)的運用 ...(1)浮點輸出中,setprecision(n)表示有效位數。    (2)定點輸出中(setiosflags(ios::fixed)),setprecision(n)表示小數點后數字位數。格式為    (3)指數形式輸出中(setiosflag
  • 正则关于有效数字的例子
  • 目录一、问题引出与求证二、问题查阅与解决三、MATLAB如何修改计算结果保留的有效数字四、拓展——数值显示四、后记 一、问题引出与求证 今天,利用MATLAB编写乘同余法产生随机数相关代码时,遇到一个问题: (下图...
  • 为了控制Java中double型数据的有效数字输出位数和精度,主要有以下三种方法: 以下以保留两位小数为例: 第一: 使用printf进行类似C语言格式输出: System.out.printf("%.2f", n); 第二 使用Strin.format() System...
  • var n = 123456.789;... //保留小数点后面几位数字,参数x代表保留位数。 toExponential(x) ; //用指数的形式转换成字符串,小数点前只有一位 ,小数点后的位数由参数x指定 ,例如x = 3,n.toExponential(x) ==
  • java中数字保留有效位数,特别在使用除法时
  • R语言设置数值输出,包括保留至小数点后几位和保留有效数字
  • 思路: 使用C++中流格式控制符对输出数值进行取舍 ...一、保留为有效数字 setprecision(n): 1.指定一个浮点数打印几位数字,其中n是总位数(包括小数之前和之后的数字),超出的位数会被四舍五入进去。 2...
  • 百度百科:从一个数的左边第一个非0数字起,到末位数字止,所有的数字都是这个数的有效数字。 就是一个数从左边第一个不为0的数字数起到末尾数字为止,所有的数字(包括0,科学计数法不计10的N次方),称为有效数字...
  • len 保留几位有效数字 * @return */ public static double round ( double d, int len) { BigDecimal b1 = new BigDecimal(d); BigDecimal b2 = new BigDecimal( 1 ); // 任何一个数字除以...
  • 近似数与有效数字的概念 近似数是由于近似存储(内存空间有限)引起的。 近似数是由四舍五入得来的数,如10/3中的3是一个准确数,而3.3是它精确到十分位的近似数。6.67是20/3精确到百分位的近似数。 而有效数字是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 87,812
精华内容 35,124
关键字:

如何判断有效数字位数