当前课程知识点:C/C++:从基础语法到优化策略 > Final Exam > Final exam > 2.3 Floating-point numbers
返回《C/C++:从基础语法到优化策略》慕课在线视频课程列表
前面我们介绍了整数的用法
现在我们来介绍一下浮点数的用法
浮点数它的写法有两种
一种是像上面这里
可以写成一个我们常用的
就是一个整数部分加一个小数部分
第二种写法就是我们所说的科学计数法
前面这一部分是它的一个小数
后面跟着e+8意思就是这是2.52乘以10的8次方这个值
那么8.33乘以10的-4四次方这样写法
那第三个就是7乘以e的5次方这样
所以这种两种写法都是正确的
大家也许觉得就是浮点数用起来比较简单
那么我给大家看一个简单的例子
这个例子是这样的
floatnumber这个例子叫
首先我们先定义million
是1x10的6次方
这个就是一百万
那么我们又定义一个tub
tub是10除以3那应该就是3.3333一直循环下去
mint的是10除以3这两个是一样的
不同的在于前面这这一个
他是10除以3之后是个浮点数
因为我们这里没加 f
没加 f 那它就是double类型的浮点数
这个double除以3之后赋给float
第二个是赋给double
这是这里的不同之处
那么在这里面如果我们把它打印出来 tub等于多少
然后第二个就是 a million tubs 100万个
100万乘以tub他的结果是多少
那我再把它打印出来
然后十百万 也就是1000万是多少
也把它打印出来
那么mint呢 mint是double类型的
前面的tub是float类型
他们的值按说应该是一样的
那么同样的我们打印mint 再打印10乘以一百万
但注意我们在这里用setf函数
把他的cout的输出设成一个固定的值
就是很长的值 这样去设的
我们来看看这个这个程序我前面这刚运行了一下
我们来重新编译一下再运行一下
这个.out a.out
大家看这个结果可能有点乱
我重新clear一下
我把结果再运行一下
我们看到tub等于3.333
就是三点后面跟着六个三
因为我们这是小数点后保存六位这种情况下
那么a million tubs 那就乘以十的六次方
那这个小数点就会挪到这个3的后面
那所以说就会变成33333333.25
这有点奇怪 按说10除以3应该是3.333这个3是无穷尽的下去
但这里没有
他到25就没了
ten million 如果继续乘
我们又发现了一个奇怪的现象
那么在这我们2看 按说这应该是个5
按照上一个结果这应该是5
为什么这个5不见了
乘以10之后这个5不见了为什么
其实是因为浮点数的精度表达不了那么高导致的
那么再来看如果是double类型好不好
double类型的话
那么这个值mint乘以1000万
那么我们可以看一直是3
一直是3看起来这个double的精度要比float高很多
这也是为什么我们在很多时候要用double
意思是我们float精度其实非常有限
我们可以看到
在大约 如果是按十进制表示的话
表示七个左右的数
那基本上就不行了就是这种程度
所以说用浮点数你不要想当然的认为
10除以3就是3.33一直下去这个3
其实对于double来讲
他也是存在这个问题
只不过是这个问题没那么严重
它的有效位数它的精度更高一点而已但是误差依然存在
好这个就是我们使用浮点数需要注意的
那么浮点数就说它有什么好处和不好的地方
好处就是他可以表达在整数不能表达
比如说在整数之间的数
比如说1.5那我们可以用浮点数来表达
整数表达不了
而且它能表达的范围又更大
范围是远大于整数的
但是它范围虽然大了
那么它如果是float 它也是32位
一个int型的整数也是32位
他们的位数是相同 也说他们的信息量是相同的
但是float的范围更大 那代表着什么
它的精度就要损失
你不可能既有精度又有范围 这个做不到
另外一个缺点或者说小缺点就是
浮点数在计算的时候
它的计算速度要比整数要稍微慢一些
所以说刚才我们提到精度的问题
所以说我们在比较两个整数(浮点数)的时候要特别小心
比如说我们不要去这样比较两个浮点数
我们不要去这样去比较两个浮点数是不是相同
是不是相同 为什么呢
我再给大家看个例子 叫fltadd
fltadd是这样的
我们先定义a是2.34乘以10的10次方
这是一个很大的数 十的10次方
那么b呢 等于a加10
b等于a加10也就是说b应该比a大10对不对
所以说如果我们把a打印出来这一行
这一行把b打印出来
那么我们看到它的值应该是b要比a大一点 对不对
然后如果 b 减 a 它的结果应该是10对不对
这是我们一般的 应该这样理解
那么我们再来编译下这个程序
看一下g++
这个命令的意思就是说
前面&&符号 前面这个命令如果编译没有出错
如果前面这个命令执行没有出错 那就执行后面这个命令
如果前面那个命令编译出错 后面的命令就不执行了但写在一起了
我们来看
这个结果有点奇怪 为什么
第一点就说
我们的a的值是2.34乘以e的10次方
那它应该是23400000000跟着八个零对不对
我们这儿呢 2339没有234跟着八个零后面跟着一堆9 还失败了
我们发现这个值不是我们想要的2.34乘以10的10次方
不是这样的 值被改了 他不是你想象的那个值
这是第一个问题
第二问题 如果我们仔细比较一下 发现a和b是相同的
a和b的值完全相同
这个很奇怪
那么我们b减a再看一看
我们会发现b减a的结果等于0
这也就证明了 就是说
a和b在这个程序里 它的值完全相同
也说a加10往上增加10 根本就没有起作用
大家可以想想
如果你在做这件事 在程序的里面
假如你用这个float表示你有这么多钱
然后你加了10块钱 存款又加了10块钱
存完之后还是这么多钱
你这十块钱不翼而飞了
这样是不是引起很严重的问题
所以呢 在这提醒大家
float甚至double
他不是你想象的那个样子
可以表示一切的数值
他的表示的精度是非常有限的
特别是float他表示的精度是有限的
这个地方你加个10他无法表示
在这么大的数的范围下 他的精度是表达不了10的
所以呢
大家使用float类型以及double类型的时候
需要特别的注意不要犯错误
否则的话你会纳闷为什么这两个值是相同的
我明明加了10 为什么他错了
他不是 b 没有比a大10呢
具体的原因大家在这儿就不展开讲
大家可以去看一看
float在二进制计算机的二进制里的存储方式是怎么存的
当你看明白了这个存储方式的话
你就明白了为什么会发生这种现象
所以说
在这里我想跟大家讲的就是
提醒大家注意的就是
float不是你想象的那个样子可以表示一切的数值
他表示的范围很有限
有些数值他根本就不存在在float类型里
就像刚才我们提到2.34乘以10的10次方
这个准确的这个数值是用float没有没法表达的
它只能用一个近似值2.3999来表达
那么在这儿我们小结一下
小结一下我们前面的这个
数据类型介绍 有整形 有浮点型 它们所占的存储的长度是不同的
这列出来这个例子是他们不同的长度
但是这个例子不是对所有的系统都是适应的
不同的系统可能有细微的差别
大家要特别的注意
比如说在这 这个long 就是跟int一样长 在这个例子里面
但是在前面我们上小节里面 我们讲的long是八个字节的
这里只有四个
这整体给大家印象就说bool类型
第一bool类型 它是有一个字节的
不要以为他是一位
他是一个字节
他是浪费了七位只用了一位
char的话 八位一个字节
wchar_t这个是两个字节 跟shot一样
int long这个是不一定的 可能是这样
float一般来说都是四个字节
double还有long double
long double是什么 那又不一样
不同的系统又会不一样
其实我个人比较喜欢这种写法 __int64
不同的环境他们也会定义自己的类型
__int32 __int64 __int16
这样好处是64这个就是多少位它就比较清晰
比较清晰否则的话我们只是看long或者long long 我们不是太确定它的长度
这需要特别注意
右上方这个表它表示的是
不同的数不同的类型他的取值范围
它的取值范围我们要特别注意
其实比如说即使int类型我们以为32位 它很大
实际上它表达的整数的范围没有你想象的大
也不是太大
它只有2乘以10多少次方
它只有2乘以10的9次方左右
你如果乘以10的10次方那他就会有问题
float的话他十进制只有七位 七位的精度
就是说你把那个数字写出来要写七个位七个数值
double 就15位
你如果连着写15个数值 第16个17个 那么他实际上是表达不出来的
所以这个事需要大家特别注意的事
不要理所当然的以为他很厉害
这就是我们第二次布置的作业让大家实现一个计算器
那是一个任意精度的计算器 它不能有精度的损失
你如果要用float或者int 甚至long
甚至long double来实现一个计算器
它是无法实现任意精度的 精度非常高的
所以大家可以思考一下这个任意精度的计算器
我们第二个作业里面
任意精度计算器应该如何来实现
-Quiz 1
-Quiz 2
-3.3 Relational expressions (> < ==)
-3.5 Branching statements (if else)
-3.8 break and continue statements
-Quiz 3
-4.4 Structures, Unions and Enumerations
-Quiz 4
-5.3 Allocate memory: C++ style
-Quiz 5
-6.3 Recursion and pointer to functions
-Quiz 6
-Quiz 7
-8.1 C/C++ with ARM development board
-Quiz 8
-9.2 Constructors and destructors
-Quiz 9
-10.1 Operators in cv::Mat in OpenCV
-10.4 Automatic conversions and type casts for classes
-Quiz 10
-11.1 Dynamic memory and classes
-11.2 New and improved String class
-11.3 Using pointers to objects
-Quiz 11
-12.2 Static and dynamic binding
-12.3 Access control: protected
-12.4 Inheritance and dynamic memory allocation
-Quiz 12
-13.1 Constructor and assignment
-13.2 Classes with object members
-Quiz 13
-14.1 CNN for image classification
-Quiz 14
-15.3 RTTI and type cast operators
-Quiz 15
-Final exam

