double类型什么时候可以直接比较相等?
#include <stdio.h>
#include<float.h>
#include <math.h>
int main()
{
float a = 1.0; // 因为整数位就表示好了。指数位都为0 所以整数的时候二进制为相等
printf("%d %d 值 %f %f %f\n", a == 1, a == 1.0, a, 1, 1.0); // 1, 1 1是代表相等
a = 0.1;
printf("%d %d 值 %f %f %f\n", a == 0.1, a == 0.1f, a , 0.1, 0.1f); // 0, 0
float a1 = 0.3;
float b1 = 0.4;
float c1 = a1 + b1;
printf("%d %d 值 %f %f %f \n", c1 == 0.7, c1 == 0.7f, c1, 0.7, 0.7f); // 0
printf("%d \n", fabs(c1 - 0.7) < FLT_EPSILON); // DBL_EPSILON
float a2 = 10.5;
float a3 = 0.5;
float c3 = a2 - a3;
printf("%d \n", c3 == 10); // 1 变成整数了,就可以相等了
}
/*
1 1 值 1.000000 1.000000 1.000000
0 1 值 0.100000 0.100000 0.100000
0 0 值 0.700000 0.700000 0.700000
1
1
*/
当然不同的编译,执行结果不同,,但是以下可以保证
1.简单的整数值, 如果两个浮点数都是整数值(没有小数部分),并且它们的值相同,那么可以直接使用"=="运算符进行比较。这是因为整数的表示方式是精确的,不会存在舍入误差) 不涉及到指数位.,直接比较二进制是相等.但是大于52bit表示整数,还是有可能会不相等)
0.前言
帧同步技术的难点之一就是需要客户端计算结果的一致性。其中浮点数的运算在一些情况下是会产生不同的结果,所以这篇文章主要是来探究浮点数相关的问题。
1.导致浮点数不确定的原因
- cpu
- 编译器
- 操作系统
- 操作系统的位数
- IEEE 754浮点数算数的标准
- 汇编指令集
总结来说,主要就是由于硬件环境和系统平台的不一致导致了浮点数会计算出不一样的结果。
关于为什么这些不一样就会导致计算结果不一样,可以参考一下这个。
用人话来说呢,计算机并不能天然处理小数,对于小数的计算,不同的编译器、处理器使用了不用的计算标准和优化方式,导致了小数的精度出现了差异。
2.浮点数解决方案
- 定点数学库
- 查表计算
- 放大截断法
定点数学库
首先要搞明白什么是浮点数,什么是定点数。
浮点:小数点非固定的数,可表示数据范围较广,整数小数都可以表示,包含float,double。
定点:小数点固定,整数小数都可以表示。int本质是小数点位于末尾的32位定点数而已。
具体可以参考这篇文章,顺便可以理解一下IEEE 754标准是什么
梦里寻梦:(二十六)通俗易懂理解——浮点与定点的计算机表示及互转141 赞同 · 14 评论文章正在上传…重新上传取消
浮点数的计算不确定性往往是出现在小数点很多位之后,这里是用定点数学库可以保证计算结果相对固定。
查表计算
通常情况下,在计算三角函数的时候,会用到查表的方式获取相应的值。
用枚举法把度数对应的值存在一个数据结构表里,如xml或者json里,这样在用到三角函数计算的时候,我们实际上是查表获取对应的值,这样就会避免在各个平台或者硬件环境下计算结果不一样的情况。
放大截断法
其实就是使用整数去替代浮点数进行的一种计算。
首先确认放大因子,比如放大10000倍,实际上就是保留了小数点后四位,然后剩余的小数部分全部截取掉。
所有参与计算的浮点数都经过了放大截断的处理然后就是纯整数之间的计算,这样就绕过了浮点数计算的。最后得到需要用来做表现逻辑的数字再除以放大因子10000,就是实际的浮点数值,因为这个值已经不需要在参与逻辑运算了,所以不会带来太大的偏差,只会用于最终的显示。
3.总结
游戏开发中,其实上面提到的三种解决方案都是需要结合到一起使用。而且如果要确定使用帧同步技术,Unity中的很多方法和系统都不能使用,例如移动方法,物理系统,寻路系统等,包括使用插件时,也要主要其实是否使用到了浮点数。