编程语言浮点数精度问题-Go语言
计算机浮点数精度问题是有限的,就像如下案例两个变量的结果明明不相等,但是会判断为true
。
package main
import "fmt"
func main() {
var a float64 = 499999998.0 / 499999999.0 // 0.999999997999999995999999992
var b float64 = (999999998.0 - 499999999.0) / (1000000000.0 - 500000000.0) // 0.999999998
fmt.Println(a == b) // true
fmt.Println(a)
fmt.Println(b)
}
/*
true
0.999999998
0.999999998
*/
其实在Python等其他编程语言也是这样
a = 499999998.0 / 499999999.0
b = (999999998.0 - 499999999.0) / (1000000000.0 - 500000000.0)
print(a==b) # True
力扣294届周赛第三题
2280. 表示一个折线图的最少线段数
给你一个二维整数数组 stockPrices ,其中 stockPrices[i] = [dayi, pricei] 表示股票在 dayi 的价格为 pricei 。折线图 是一个二维平面上的若干个点组成的图,横坐标表示日期,纵坐标表示价格,折线图由相邻的点连接而成。比方说下图是一个例子:
请你返回要表示一个折线图所需要的 最少线段数 。
示例 1:
输入:stockPrices = [[1,7],[2,6],[3,5],[4,4],[5,4],[6,3],[7,2],[8,1]]
输出:3
解释:
上图为输入对应的图,横坐标表示日期,纵坐标表示价格。
以下 3 个线段可以表示折线图:
- 线段 1 (红色)从 (1,7) 到 (4,4) ,经过 (1,7) ,(2,6) ,(3,5) 和 (4,4) 。
- 线段 2 (蓝色)从 (4,4) 到 (5,4) 。
- 线段 3 (绿色)从 (5,4) 到 (8,1) ,经过 (5,4) ,(6,3) ,(7,2) 和 (8,1) 。
可以证明,无法用少于 3 条线段表示这个折线图。
示例 2:
输入:stockPrices = [[3,4],[1,2],[7,8],[2,3]]
输出:1
解释:
如上图所示,折线图可以用一条线段表示。
思路
- 排序+判断斜率
- 精度问题会卡点
Δ y i − 1 Δ x i − 1 = Δ y i Δ x i ⟺ Δ y i − 1 Δ x i = Δ y i Δ x i − 1 \frac{\Delta y_{i-1}}{\Delta x_{i-1}} = \frac{\Delta y_{i}}{\Delta x_{i}} \iff \Delta y_{i-1}\Delta x_{i} = \Delta y_{i}\Delta x_{i-1} Δxi−1Δyi−1=ΔxiΔyi⟺Δyi−1Δxi=ΔyiΔxi−1
func minimumLines(stockPrices [][]int) int {
res := 0
n := len(stockPrices)
if n == 1 {
return res
}
sort.Slice(stockPrices,func(i,j int) bool {return stockPrices[i][0] < stockPrices[j][0]})
var dy,dx,pre_dy,pre_dx int
pre_dy,pre_dx = stockPrices[1][1]-stockPrices[0][1],stockPrices[1][0]-stockPrices[0][0]
res++
for i := 2; i < n; i++ {
dy,dx = stockPrices[i][1]-stockPrices[i-1][1],stockPrices[i][0]-stockPrices[i-1][0]
if pre_dy*dx != pre_dx*dy {
res++
pre_dy,pre_dx = dy,dx
}
}
return res
}
还可以用真分数来表示
func minimumLines(stockPrices [][]int) int {
res := 0
n := len(stockPrices)
if n == 1 {
return res
}
sort.Slice(stockPrices,func(i,j int) bool {return stockPrices[i][0] < stockPrices[j][0]})
var k [2]int
k = trans(stockPrices[1][1]-stockPrices[0][1],stockPrices[1][0]-stockPrices[0][0])
res++
for i := 2; i < n; i++ {
if k != trans(stockPrices[i][1]-stockPrices[i-1][1],stockPrices[i][0]-stockPrices[i-1][0]) {
res++
k = trans(stockPrices[i][1]-stockPrices[i-1][1],stockPrices[i][0]-stockPrices[i-1][0])
}
}
return res
}
func gcd(a,b int) int {
if b == 0 {
return a
}
return gcd(b,a%b)
}
func trans(a,b int) [2]int {
div := gcd(a,b)
return [2]int{a/div,b/div}
}