编程语言浮点数精度问题-Go语言

编程语言浮点数精度问题-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 。折线图 是一个二维平面上的若干个点组成的图,横坐标表示日期,纵坐标表示价格,折线图由相邻的点连接而成。比方说下图是一个例子:

img

请你返回要表示一个折线图所需要的 最少线段数 。

示例 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:

img

输入: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} Δxi1Δyi1=ΔxiΔyiΔyi1Δxi=ΔyiΔxi1

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}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值