網站首頁 編程語言 正文
一、浮點數是什么?
浮點數,是屬于有理數中某特定子集的數的數字表示,在計算機中用以近似表示任意某個實數。浮點數在計算機中主要用來表示小數,浮點數就是小數點可以出現改變的數字。
因為在計算機的機器語言中,只有二進制,機器語言只能識別0和1。所以,計算機也是不可能存儲小數的,所以需要有另一種變通的存儲方案。
這種方案就是:
1.指數方案
指數形式:其數值部分是一個小數,小數點前的數字是零,小數點后的第一位數字不是零。一個實數可以有多種指數表示形式,但只有一種屬于標準化指數形式。
? | ? |
---|---|
12.3 | 1.23*10^-1 |
1.23 | 1.23*10^0 |
1.23 | 0.123*10^1 |
上面的表格,我們可以很清晰的了解指數方案。同樣的我們也就能發現這樣表達小數會有一個嚴重的問題,那就是指數表示形式太多了,如果不能約定好唯一形式,不同代碼之間溝通將會出現問題。
2.規范化指數形式
在指數形式的多種表示方式中把小數部分中小數點前的數字為0、小數點后第1位數字不為0的表示形式稱為規范化的指數形式。
1.23 的規范化的指數形式 0.123*10^1
一個實數只有一個規范化的指數形式,在程序以指數形式輸出一個實數時,必然以規范化的指數形式輸出。
0.123e001
1.為什么要以 0 開頭
1.23456要二進制存放需分別存整數部和小數部,而0.123456則只需存小數部,這樣在占用相同字節的情況下,后一種方法可容納更大精度的浮點數。
2.為什么 e 后面要加 0 ,e001 和 e1 一樣嗎
后面加 0 是 %e 的輸出格式,并不是規范化的指數形式所必需的,
e001 和 e1 是一樣的
3.IEEE 754標準
由于不同機器對浮點數的表示有較大差別,這不利于軟件在不同計算機之間的移植。為此,美國IEEE提出了一個從系統角度支持浮點數的表示方法,稱為IEEE754標準(IEEE,1985),當今流行的計算機幾乎都采用了這一標準。
IEEE 754規定了四種表示浮點數值的方式:單精確度(32位)、雙精確度(64位)、延伸單精確度(43比特以上,很少使用)與延伸雙精確度(79比特以上,通常以80位實現)。只有32位模式有強制要求,其他都是選擇性的。
二、出現精度問題的情況
1.浮點數加減運算
輸入數據:
a = 2.3329 b = 3.1234
代碼如下(示例):
package main import "fmt" func main() { // a = 2.3329 b = 3.1234 a, b := 2.3329, 3.1234 c := a + b fmt.Println(c) //5.456300000000001} }
結果精度出現問題
2.3329 + 3.1234 = 5.456300000000001
已經出錯
2.float64與float32之間轉換
輸入數據:
a = 9.99999
代碼如下(示例):
package main import "fmt" func main() { var a float32 a = 9.99999 b := float64(a) fmt.Println(b) //9.999990463256836} }
結果精度出現問題
9.99999 = 9.999990463256836
已經出錯
3.int64和float64,int32和float32轉換
1.int32和float32轉換
輸入數據:
a = 9.99999
代碼如下(示例):
package main import "fmt" func main() { var a int32 a = 999990455 b := float32(a) fmt.Printf("%f\n", b) //999990464.000000} }
結果精度出現問題
999990455= 999990464.000000
已經出錯
2.int64和float64轉換
輸入數據:
a = 999999942424527242
代碼如下(示例):
package main import "fmt" func main() { var a int64 a = 999999942424527242 b := float64(a) fmt.Printf("%f\n", b) //999999942424527232.000000} }
結果精度出現問題
999999942424527242 = 999999942424527232.000000
已經出錯
4.float64位直接乘100
輸入數據:
a = 999999942424527242
代碼如下(示例):
package main import "fmt" func main() { var a float64 a = 1128.61 b := a * 100 fmt.Println(b) //112860.99999999999} }
結果精度出現問題
1128.61 * 100= 112860.99999999999
已經出錯
三、decimal 解決精度問題
利用 Decimal 包解決精度問題
go get github.com/shopspring/decimal
1.浮點數加減運算
輸入數據:
a = 2.3329 b = 3.1234
代碼如下(示例):
package main import ( "fmt" "github.com/shopspring/decimal" ) func main() { // a = 2.3329 b = 3.1234 a, b := 2.3329, 3.1234 c := decimal.NewFromFloat(a) d := decimal.NewFromFloat(b) fmt.Println(a, b) fmt.Println(c, d) fmt.Println("此時ab 與 cd 相同") fmt.Println(a + b) //5.456300000000001} fmt.Println(c.Add(d)) //5.4563} }
結果精度不再出現問題
2.float64與float32之間轉換
輸入數據:
a = 9.99999
代碼如下(示例):
package main import ( "fmt" "github.com/shopspring/decimal" ) func main() { var a float32 a = 9.99999 c := decimal.NewFromFloat32(a) b := float64(a) c.Float64() fmt.Println(b) //9.999990463256836} fmt.Println(c.Float64()) //9.99999} }
結果精度不再出現問題
3.float64位直接乘100
輸入數據:
a = 999999942424527242
代碼如下(示例):
package main import ( "fmt" "github.com/shopspring/decimal" ) func main() { var a float64 a = 1128.61 c := decimal.NewFromFloat(a) b := a * 100 fmt.Println(b) //112860.99999999999} fmt.Println(c.Mul(decimal.NewFromInt(100))) //112861} }
結果精度不再出現問題
總結
通過以上兩個例子,我們已經了解了浮點數的精度問題,那么在工作中,我們就需要更換運算方式。我們需要盡量選擇Decimal,否則如果使用 Float 出現精度問題之后,到那時再更換方法,既費時又費力,能剛開始就解決,何樂而不為呢。
原文鏈接:https://blog.csdn.net/moer0/article/details/122992424
相關推薦
- 2022-06-12 C#泛型接口的協變和逆變_C#教程
- 2022-06-18 go語言實現Elasticsearches批量修改查詢及發送MQ操作示例_Golang
- 2022-12-30 解決React報錯Style?prop?value?must?be?an?object_React
- 2023-05-29 Postgresql數據庫角色創建登錄詳解_PostgreSQL
- 2022-04-28 C++實現簡單班級成績管理系統_C 語言
- 2022-03-30 SQL基礎查詢和LINQ集成化查詢_MsSql
- 2022-11-14 Swift?指針底層探索分析_Swift
- 2022-11-26 詳解vant2?自動檢查表單驗證?-validate_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支