在《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中有“有效位数”这一概念,也就是为什么会存在误差?
以上问题,以后再详细阐述,今天先到这里。