File tree Expand file tree Collapse file tree 1 file changed +71
-0
lines changed
Expand file tree Collapse file tree 1 file changed +71
-0
lines changed Original file line number Diff line number Diff line change 1+ package main
2+
3+ import (
4+ "fmt"
5+ "math/big"
6+ )
7+
8+ // 经典语言问题
9+ // float 类型的 a + b 不等于 a + b
10+
11+ func main () {
12+
13+ var a , b = 0.1 , 0.2
14+ var c = a + b
15+ var d = 0.3
16+
17+ fmt .Println (c == d )
18+ fmt .Println ("a + b =" , c )
19+
20+ // 上述程序的输出结果是:
21+ // Macos M4 芯片
22+ // false
23+ // a + b = 0.30000000000000004
24+ // 可以看出是有差异的
25+
26+ fmt .Println ("===================================" )
27+
28+ // 其中一种解决方法是:使用 math/big 包中的 big.Float 类型来进行高精度的浮点数计算。
29+ var e , f = big .NewFloat (0.1 ), big .NewFloat (0.2 )
30+ var g = new (big.Float ).Add (e , f )
31+ var h = big .NewFloat (0.3 )
32+
33+ // 在判断相等时,使用一个差值来比较
34+ fmt .Println (EqualFloat (g , h ))
35+ fmt .Println ("e + f = " , g )
36+ }
37+
38+ // CustomFloat 定义一个类型约束,支持 float64 和 float32
39+ type CustomFloat interface {
40+ float64 | float32 | * big.Float
41+ }
42+
43+ // float 类型比较的容差值
44+ const epsilon = 1e-10
45+
46+ func EqualFloat [T CustomFloat ](a , b T ) bool {
47+
48+ // 使用 *big.Float 进行比较
49+ var bigA , bigB * big.Float
50+
51+ switch v := any (a ).(type ) {
52+ case float64 :
53+ bigA = big .NewFloat (v )
54+ case float32 :
55+ bigA = big .NewFloat (float64 (v ))
56+ case * big.Float :
57+ bigA = v
58+ }
59+
60+ switch v := any (b ).(type ) {
61+ case float64 :
62+ bigB = big .NewFloat (v )
63+ case float32 :
64+ bigB = big .NewFloat (float64 (v ))
65+ case * big.Float :
66+ bigB = v
67+ }
68+
69+ diff := new (big.Float ).Sub (bigA , bigB )
70+ return diff .Abs (diff ).Cmp (big .NewFloat (epsilon )) < 0
71+ }
You can’t perform that action at this time.
0 commit comments