浮点数初探及C++类型转换规则

来源:互联网 发布:综琼瑶 知君用心 编辑:程序博客网 时间:2024/06/07 05:21

浮点数简要介绍:

浮点数是C++的第二组基本类型。我们对浮点数最直观的认识就是能表示带小数部分的数字。但浮点数在计算机究竟是如何存储及表示的呢?以十进制数824.338.2433为例,这两个数的区别在于小数点的位置。我们都知道,这两个数用科学计数法可以分别表示成8.2433×1028.2433×101,浮点数为计算机用一个定点数与一个基数(一般为2)的幂的乘积来近似(注意是近似)表示一个实数,这种表示方法类似于科学计数法。浮点数的一般形式为:

浮点数=尾数×基数^阶码(N=M*RE


以图为例,尾数部分,第一位为符号位,0为正1为负,后面8位表示尾数的数字部分,对于阶码部分道理是一样的。所以这个数是0.11111111×2111111,用十进制表示就是0.99609375×263=9187343239835811840

关于浮点数的更详细知识及其运算法则在此不再深入。

下面来看各类型浮点数的内存占用及表示范围(不同编译器和系统会产生不同结果):

#include <iostream>using namespace std;int main (void){    cout << "浮点型数据内存占用:" << endl;    cout << "float is " << sizeof(float) << "bytes" << endl;    cout << "double is " << sizeof(double) << "bytes" << endl;    cout << "long double is " << sizeof(long double) << "bytes" << endl;    cout << endl;    cout << "浮点型数据范围:" << endl;    //cout.setf(ios_base::fixed, ios_base::floatfield);    cout << "float:       " << __FLT_MIN__ << "~" << __FLT_MAX__ << endl;    cout << "double:      " << __DBL_MIN__ << "~" << __DBL_MAX__ << endl;    cout << "long double: " << __LDBL_MIN__ << "~" << __LDBL_MAX__ << endl;    return 0;}

由程序运行结果可以看出,浮点数的表示范围远远大于整型数据,其内存占用也高于一般整型数据。浮点数与整数相比除了可以表示更大范围的整数以外还可以表示小数部分,但浮点运算的速度比整数运算慢,而且精度较低。从下面这个程序可以直观体现:

#include <iostream>using namespace std;int main (void){    float a = 2.34e+22f;    float b = a-1.0f;    cout << "a = " << a << endl;    cout << "b-a = " << b-a << endl;    return 0;}

我们口算可以就得出正确结果为1,但程序运行结果如下:


问题在于,2.34e+22是一个小数点左边有23位的数字,但float类型只能表示数字中的前6位或前7位,因此修改第23位对这个值不会有任何影响。

从上面的例子就可以看出浮点数与整型相比在精度上的劣势,尤其当进行除法运算时尤为明显,比如经过一系列运算我们可能会得到一个0.9999999的数字(正确结果应该是1),经过四舍五入得到1,一旦在这之前将其强制转换为int型就会得到0的错误结果。

C++类型转换规则:

C++在如下情况会自动执行类型转换:

初始化和赋值

#include <iostream>using namespace std;int main (void){    int a = 24.12;    cout << a << endl;    double b = 24.12;    a = b;    cout << a << endl;    int c = 24;    b = c;    cout.setf(ios_base::fixed, ios_base::floatfield);    cout << b << endl;    return 0;}


从程序运行结果可以看出,将一个值赋给值取值范围更大的类型通常不会导致什么问题,只是占用了更多字节而已,但反过来的话就会被降低精度。

{}方式初始化时进行的转换(C++11)

C++11将使用大括号的初始化称为列表初始化,因为这种初始化常用于给复杂的数据类型提供值列表。它对类型转换的要求更为严格,只有在编译器知道目标变量能够正确地存储赋给它的值时这种转换才被允许(通俗来说就是列表初始化不允许缩窄)。

表达式中的转换

当同一个表达式中出现了不同的数据类型,编译器就会根据校验表来进行类型转换,校验表的内容如下:

1)如果有一个操作数的类型是long double,则将另一个操作数转换为long double

2)否则,如果有一个操作数的类型是double,则将另一个操作数转换为double

3)否则,如果有一个操作数的类型是float,则将另一个操作数转换为float

4)否则,说明操作数都是整型,因此执行整型提升(整型提升:C++boolcharunsigned charsigned charshort值转换为int);

5)在这种情况下,如果两个操作数都是有符号或无符号的,且其中一个操作数的级别比另一个低,则转换为级别高的类型;

6)如果一个操作数为有符号的,另一个操作数为无符号的,且无符号操作数的级别比有符号操作数的级别高,则将有符号操作数转换为无符号操作数所属的类型;

7)否则,将两个操作数都转换为有符号类型的无符号版本。

参数传递时转换

在参数传递时遇到类型不同的情况将自动按照级别从低到高的原则进行转换(除非人为取消)。

强制类型转换

通过强制类型转换机制显式地进行类型转换,有如下格式(后四种针对特定类型):

(<typename>) value

<typename> (value)

dynamic_cast

const_cast

static_cast

reinterpret_cas


此外,在C++中我们可以不指定变量的类型,而用auto关键字,这种情况下编译器将把变量的类型设置成与初始值相同(一般在处理复杂类型时才会用到)。

总的来说,C++的自动转换遵循以不丢失数据为最基本原则。

整型级别

有符号整型按级别从高到低依次为long long、long、int、short和signed char。无符号整型的排列顺序与有符号整型相同。类型char、signed char和unsigned char的级别相同。类型bool的级别最低。wchar_t、char_16t和char_32t的级别与其底层类型相同。


关于C++另一组基本数据类型——整型的相关知识在另一篇博文:大整数构造前需要了解的:整型数据类型(含计算方法)及内存占用


本文为博主学习《C++ Primer Plus(第6版)中文版》第三章相关内容后整理得到








0 0