[英]Go: Converting float64 to int with multiplier
我想轉換一個float64
號碼,比方說1.003
到1003
(整數類型)。 我的實現只是將float64
與1000
相乘並將其轉換為int
。
package main
import "fmt"
func main() {
var f float64 = 1.003
fmt.Println(int(f * 1000))
}
但是當我運行該代碼時,我得到的是1002
而不是1003
。 因為Go會自動將1.003
存儲為1.002999...
在變量中。 在Golang上進行這種操作的正確方法是什么?
數字類型之間的轉換
將浮點數轉換為整數時,將丟棄該分數(截斷為零)。
所以基本上當你將浮點數轉換為整數時,只保留整數部分。
如果您只是想避免因使用有限位表示而產生的錯誤,只需在將數字轉換為int
之前將數字加0.5
即可。 無需外部庫或函數調用(來自標准庫)。
由於float -> int
轉換不是舍入而是保留整數部分 ,因此這將為您提供所需的結果。 考慮到可能的更小和更大的代表性:
1002.9999 + 0.5 = 1003.4999; integer part: 1003
1003.0001 + 0.5 = 1003.5001; integer part: 1003
所以簡單地寫一下:
var f float64 = 1.003
fmt.Println(int(f * 1000 + 0.5))
將它包裝成一個函數:
func toint(f float64) int {
return int(f + 0.5)
}
// Using it:
fmt.Println(toint(f * 1000))
在Go Playground上試試吧 。
注意:
如果是負數,請小心使用! 例如,如果您的值為-1.003
,那么您可能希望結果為-1003
。 但是如果你加0.5
:
-1002.9999 + 0.5 = -1002.4999; integer part: -1002
-1003.0001 + 0.5 = -1002.5001; integer part: -1002
因此,如果您有負數,則必須:
0.5
而不是添加它 0.5
但從結果中減去1
將此結合到我們的輔助函數中:
func toint(f float64) int {
if f < 0 {
return int(f - 0.5)
}
return int(f + 0.5)
}
正如威爾所提到的,這歸結為浮動在各種平台上的表現方式。 基本上你需要對浮點數進行舍入而不是讓默認的截斷行為發生。 這沒有標准的庫函數,可能是因為有很多可能的行為,實現起來很簡單。
如果你知道你總是有所描述類型的錯誤,你所需的值(130099000)略低於(1299.999999)你可以使用數學庫的Ceil
函數:
f := 1.29999
n := math.Ceil(f*1000)
但是,如果您有不同類型的浮動錯誤並想要更通用的排序行為? 使用數學庫的Modf
函數將浮點值與小數點分開:
f := 1.29999
f1,f2 := math.Modf(f*1000)
n := int(f1) // n = 1299
if f2 > .5 {
n++
}
fmt.Println(n)
您可以自己在游樂場中運行此代碼的稍微更通用的版本。
在大多數編程語言中,這通常可能是浮點問題,盡管有些實現與其他編程語言不同。 我不會在這里討論復雜的問題,但是大多數語言通常采用“十進制”方法作為標准庫或第三方庫來獲得更精確的。
例如,我發現inf.v0包非常有用。 該庫的底層是一個Dec
結構,它包含指數和整數值。 因此,它能夠將1.003
保持為1003 * 10^-3
。 請參閱下面的示例:
package main
import (
"fmt"
"gopkg.in/inf.v0"
)
func main() {
// represents 1003 * 10^-3
someDec := inf.NewDec(1003, 3)
// multiply someDec by 1000 * 10^0
// which translates to 1003 * 10^-3 * 1000 * 10^0
someDec.Mul(someDec, inf.NewDec(1000, 0))
// inf.RoundHalfUp rounds half up in the 0th scale, eg. 0.5 rounds to 1
value, ok := someDec.Round(someDec, 0, inf.RoundHalfUp).Unscaled()
fmt.Println(value, ok)
}
希望這可以幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.