Skip to content

Commit ed4eb59

Browse files
committed
add float equal
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
1 parent aec18fd commit ed4eb59

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

grammar/number/float/main.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
}

0 commit comments

Comments
 (0)