我的问题看起来很简单,但我还没有解决它.. 用户输入金额xx.xx作为字符串。之后我将字符串转换为浮点值(一些美元,一些美分),例如,让它为655.18(float64) 然后,我需要将此金额转换为美分 - 655.18 * 100,结果为65517.9999999,所以当我将此值转换为int时,我得到65517,因此丢失了1美分。 我该如何避免这种行为?
代码:
package main
import (
"fmt"
"strconv"
)
func CheckParamsPur(sa string) (amount float64) {
amount, _ = strconv.ParseFloat(sa, 64)
return amount
}
func main() {
fmt.Print("Enter a number: ")
var input string
fmt.Scanf("%s", &input)
amount := int(CheckParamsPur(input) * (100))
fmt.Println(amount)
}
答案 0 :(得分:4)
string
到浮点数到整数如果您首先要将数量解析为浮点数,那么在下一步而不是转换中,请使用舍入。
由于转换会保留整数部分,在转换之前将<{1}}添加到其中。因此,如果小数部分小于0.5
,则添加0.5
不会增加整数部分,因此转换后整数部分将相同(向下舍入)。如果小数部分大于0.5,则向其添加0.5将增加整数部分,并且在转换之后,我们得到原始整数部分的1(向上舍入)。
在您的情况下,在乘以100之后,在进行转换之前添加0.5 :
0.5
输出(在Go Playground上尝试):
f := 655.17
i := int(f*100 + 0.5)
fmt.Println(i)
阅读相关问题,其中包含以下内容:Golang Round to Nearest 0.05
另一种选择是完全跳过浮点数。为此,我们可以解析应该保存浮点数的输入65517
为2个整数,用点string
分隔:.
(其中"dollars.cents"
和{{ 1}}都是整数):
dollars
再次输出(在Go Playground上尝试):
cents
注意:上述解析代码要求您使用2位数输入分数,例如: s := "655.17"
var dollars int64
var cents uint64
if _, err := fmt.Sscanf(s, "%d.%d", &dollars, ¢s); err != nil {
panic(err)
}
if cents > 99 {
panic("cents cannot be greater than 99")
}
var total int64
if dollars >= 0 {
total = dollars*100 + int64(cents)
} else {
total = dollars*100 - int64(cents)
}
fmt.Println(total)
,输入65517
会产生糟糕的结果。
答案 1 :(得分:2)
不要使用花车作为货币。使用代表美分的整数代替。
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
input := "655.18"
c := strings.Replace(input, ".", "", -1)
cents, _ := strconv.ParseInt(c, 10, 64)
fmt.Println(cents)
}
你可能也应该整理用户输入,因为它们可能会给你.40或4.50或40美元,但这很容易做,虽然它是一个字符串,可以成为你的转换方法的一部分。在转换之前执行此操作,然后您可以将字符串解析为美分。你应该有一个用于用户输入的stringToCents方法和一个用于格式化边界的货币的一种美分技术方法,其他地方都使用美分。
如果你解析并存储为美分,你将始终必须显式转换为浮点数,然后返回美分,你将永远不会对浮点数中的舍入规则或不准确性感到惊讶,因为你明确说明舍入将用于每个计算(有很多关于货币舍入的任意规则,这变成了necc。与浮点数的问题完全不同)。
请参阅此相关问题的答案,了解更多可以解决此问题的示例。