【C++ Primer】详解C++和C中的float中的有效数字

时间:2024-03-01 14:48:57

  在《C++ Primer》第二章中,2.1.1讲到float型的最小尺寸是6位有效数字。这里对“有效数字”的概念产生疑问,故有了以下内容。

       首先,float的“尺寸”的意思是该类型数据所占的比特数,在不同机器上有所差别。而“最小尺寸”是C++标准规定的尺寸的最小值,同时允许编译器赋予这些类型更大的尺寸,有些编译器float的有效位数是7或者8位。
       float的6位”有效数字“的意思是说能保证该float型数据从最左边的非零数字开始的前6位是准确的,后面的就不一定了,可能会错。
       我们先来验证一下,这里我使用的编译器是codeblocks:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
    float a=01234.56789;
    cout<<"c++: "<<a;
    printf("\nc: %f\n",a);
    return 0;
}

  我们定义了一个float型数据,

       Case 1: a=01234.56789发现结果如下:
        

 

  可以发现:
  1.    C++中的cout真的只会输出前6位,但是第6位并不像之前说的是准确的“6”,我们可以假设它是做了四舍五入;
  2.    C的printf("%f")则会输出10位,小数点后会输出6位。而前8位是准确的,后2位则完全不准。
       
  Case 2:    a=1.23456789 或 1.23456123。发现结果如下:
        

  

  可以发现:
  1.    C++中第6位确实是做了四舍五入;
  2.    C中则还是固定输出小数点后6位,而从“1”开始的前6位是准确的,第7位做了四舍五入。
        
  Case 3:    a=0.123456789。发现结果如下:
        

 

  可以发现:
  1.    C++还是照常进行四舍五入的计算然后输出前6位
       2.    而C中在第6位做了四舍五入,看似好像开始不符合它的前六位一定准确的规定,但是其实还是符合的。因为C一定会输出小数点后6位,所以在第6位的时候它已经没有机会继续输出数字了,所以它要把握机会实现“前6位一定准确”,所以它要对第6位做四舍五入来保证这一点。
        综上所述:
       1.    C++的cout对float型数据会坚持只输出从最左边的非零数字开始的前6位数字,且在计算第6位的时候会对其进行四舍五入;
       2.    C中的printf("%f")默认对float型数据一定会输出小数点后6位,当原数据的第6位数字后面还有数字且第6位数字不是在小数点后面的第6位时,它会保证前6位一定跟原数字的前6位一模一样;而当第6位数字位于小数点后面的第6位时,也就是0.123456XXX,它会对第6位进行四舍五入,可能会跟原数字的第6位不一样了。
       所以,float的“6位有效数字”在C++和C中实际都是指在进行四舍五入的基础上保证的前6位一定准确,而准确不意味着跟原数字的前6位一模一样。
       但我们仍有以下问题,待续。。。。
       1. 当C中的float型数据小数点后不足6位,那么输出的时候小数点后6位不足的部分的数字是怎么获取的?
       2. 在C中当使用%f的时候,实际上已经指定了输出位数,而C是可以自己指定输出位数的,怎么实现呢?
       3. 为什么C++和C中有“有效位数”这一概念,也就是为什么会存在误差?
       以上问题,以后再详细阐述,今天先到这里。