wochai 发表于 2021-5-25 17:00:54

VS2015:目标平台在x86和x64下double计算问题

本帖最后由 wochai 于 2021-5-25 18:38 编辑

C#代码如下:   
             int AngleSweep = 360;
            double SequenceDisplayMin = 737933.5;
            double SequenceDisplayMax = 737934;
            float[] m_TrackValue = new float { 737933,0.6378019f};
          //结果应为99.21736802905798, x64和Any CPU下实际计算结果为90,x86下正常
            double Angle = AngleSweep * (m_TrackValue + m_TrackValue - SequenceDisplayMin) / (SequenceDisplayMax - SequenceDisplayMin);
            //结果始终正确
            Angle = 360 * (737933 + 0.6378019 - SequenceDisplayMin) / (SequenceDisplayMax - SequenceDisplayMin);


???????????????

wochai 发表于 2021-5-25 17:01:46

int AngleSweep = 360;
            double SequenceDisplayMin = 737933.5;
            double SequenceDisplayMax = 737934;
            float[] m_TrackValue = new float { 737933,0.6378019f};
            //这样始终正常正常
            double Angle = AngleSweep * ((double)m_TrackValue +(double) m_TrackValue - SequenceDisplayMin) / (SequenceDisplayMax - SequenceDisplayMin);
            //结果始终正确
            Angle = 360 * (737933 + 0.6378019 - SequenceDisplayMin) / (SequenceDisplayMax - SequenceDisplayMin);

redroof 发表于 2021-5-25 18:25:23

一个简单的规则:除非是纯整数运算并且你知道你希望对除法取整,否则应当手工写类型强转,全转成double来做计算。

redroof 发表于 2021-5-25 18:27:40

你错在m_TrackValue + m_TrackValue
两个float相加的结果是float,丢了精度
手工带上强转double就对了

wochai 发表于 2021-5-25 18:30:23

redroof 发表于 2021-5-25 18:27
你错在m_TrackValue + m_TrackValue
两个float相加的结果是float,丢了精度
手工带上强转double就对 ...

整个算式中有double类型,理论上应该自动提升的!
而且在目标平台x86下是正常的!

wochai 发表于 2021-5-25 18:38:50

前面忘写了,是C# 2015

redroof 发表于 2021-5-25 19:03:42

wochai 发表于 2021-5-25 18:30
整个算式中有double类型,理论上应该自动提升的!
而且在目标平台x86下是正常的! ...

你不该依赖这个。
2个float再加一个double,前两个是float加float,不一定会提升,这俩的结果加上double,这个时候才保证会提升。

wudicgi 发表于 2021-5-25 19:15:31

学到了个新知识

搜 C# double float x86 x64 能找到不少东西,比如这篇:
C#因x86-x64环境不同引发的浮点”bug”~

wudicgi 发表于 2021-5-25 19:17:16

我自己不管是写 C 还是 C# 程序,能用 double 都不会用 float, float 的范围还是有点小了

liwei_jlu 发表于 2021-5-25 19:58:58

float精度只有6~7位有效数字。要求高精度,必须手动确保double类型

brother_yan 发表于 2021-5-25 23:05:44

说一个很少有人注意的,FPU是80位的,所以最好的数据类型是float128。double也会导致精度损失,只是一般人没发现而已

wochai 发表于 2021-5-26 09:05:42

wudicgi 发表于 2021-5-25 19:15
学到了个新知识

搜 C# double float x86 x64 能找到不少东西,比如这篇:


是的,一直用的x86目标平台,前两天才因为一个DLL的原因使用x64目标平台,一下把我搞蒙了.

wochai 发表于 2021-5-26 09:07:34

brother_yan 发表于 2021-5-25 23:05
说一个很少有人注意的,FPU是80位的,所以最好的数据类型是float128。double也会导致精度损失,只是一般人 ...

精度丢失可以理解.
以前还专门买过一本计算方法的书,里面就提到了如何通过改变计算方法以避免精度问题造成的计算错误.

wochai 发表于 2021-5-26 09:08:24

liwei_jlu 发表于 2021-5-25 19:58
float精度只有6~7位有效数字。要求高精度,必须手动确保double类型

是的.
主要是x86正常影响了我的判断.

wochai 发表于 2021-5-26 09:09:55

wudicgi 发表于 2021-5-25 19:17
我自己不管是写 C 还是 C# 程序,能用 double 都不会用 float, float 的范围还是有点小了
...

我这因为是一个较大的数组,还需要保存,所以采用了float来减少尺寸.

wochai 发表于 2021-5-26 09:10:24

redroof 发表于 2021-5-25 19:03
你不该依赖这个。
2个float再加一个double,前两个是float加float,不一定会提升,这俩的结果加上double ...

是的,吃一堑长一智.

redroof 发表于 2021-5-26 10:09:28

brother_yan 发表于 2021-5-25 23:05
说一个很少有人注意的,FPU是80位的,所以最好的数据类型是float128。double也会导致精度损失,只是一般人 ...

x87的内部数据类型就是这种,某些编译器可以用 long double 来明确表示这种数据类型。
但是x64上面默认是用SSE的,而不是x87,所以默认没有这种了。
x87比SSE慢,而且不灵活,基本上该淘汰了,除非你需要这一点多岀来的精度。double一般都够用了,明显不够的场合你多这一点也还是不够。

redroof 发表于 2021-5-26 10:10:44

wochai 发表于 2021-5-26 09:09
我这因为是一个较大的数组,还需要保存,所以采用了float来减少尺寸.

存储可以是float,但是所有的计算应该明确的用double来做。

初音之恋 发表于 2021-5-26 10:33:52

C#的强制转换和Convert.ToXX是不一样的,尽量不要用强制转换,Single与float也有点不一样

brother_yan 发表于 2021-5-26 11:40:34

redroof 发表于 2021-5-26 10:09
x87的内部数据类型就是这种,某些编译器可以用 long double 来明确表示这种数据类型。
但是x64上面默认是 ...

测试了一下,确实这样,看来我知识要更新了,多谢!
页: [1]
查看完整版本: VS2015:目标平台在x86和x64下double计算问题