使用 decimal 函数返回错误的值。

huangapple go评论81阅读模式
英文:

using decimal the function returns wrong value

问题

我的功能对于输入值2.3返回了错误的值,返回的是229,但应该是230。只有在这个值上才会出现这种情况,其他情况下一切正常。我已经明白问题出在浮点数的存储和四舍五入上。但我还没有弄清楚如何修复这个函数。是使用shopspring/decimal、big.rat还是big.int?

import (
	"fmt"
	"math"
	"strconv"
)

func check_commission(number string) uint64 {
	tempValue, err := strconv.ParseFloat(number, 64)

	if err != nil || math.IsNaN(tempValue) || strconv.FormatFloat(tempValue, 'f', -1, 64) == "+Inf" {
		fmt.Println("Not a number:", number)
		return 0
	}

	if tempValue < 0 || tempValue > 99.99 {
		fmt.Println("Commission ", tempValue," out of range")
		return 0
	}

	var x = tempValue - math.Floor(tempValue)
	if x > 0 {
		tempValue *= 100
	}
	result := uint64(tempValue)

	return result
}

func main() {
	input := "1.5"
	fmt.Println("\nInput value:", input)
	fmt.Println("Output value:", check_commission(input))

	input = "15"
	fmt.Println("\nInput value:", input)
	fmt.Println("Output value:", check_commission(input))

	input = "2.3"
	fmt.Println("\nInput value:", input)
	fmt.Println("Output value:", check_commission(input))
}

该函数检查输入值的正确性。
关键在于佣金的大小可以从0到99.99。小数位数的最大值为2。
函数只能返回整数值,因此逗号必须向后移动2个字符。
例如,对于佣金1.5,返回值将是150。如果是15,则返回15。

如何正确修复这个函数?链接到play go

英文:

My function returns the wrong value for input value 2.3 - 229 is returned, but should be 230. This only happens with this value, otherwise everything works well. I already understood that the point is how float numbers are stored and how they are rounded. But I have not yet figured out how can I fix this function? shopspring/decimal, big.rat or big.int?

import (
	&quot;fmt&quot;
	&quot;math&quot;
	&quot;strconv&quot;
)

func check_commission(number string) uint64 {
	tempValue, err := strconv.ParseFloat(number, 64)

	if err != nil || math.IsNaN(tempValue) || strconv.FormatFloat(tempValue, &#39;f&#39;, -1, 64) == &quot;+Inf&quot; {
		fmt.Println(&quot;Not a number:&quot;, number)
		return 0
	}

	if tempValue &lt; 0 || tempValue &gt; 99.99 {
		fmt.Println(&quot;Commission &quot;, tempValue,&quot; out of range&quot;)
		return 0
	}

	var x = tempValue - math.Floor(tempValue)
	if x &gt; 0 {
		tempValue *= 100
	}
	result := uint64(tempValue)

	return result
}

func main() {
	input := &quot;1.5&quot;
	fmt.Println(&quot;\nInput value:&quot;, input)
	fmt.Println(&quot;Output value:&quot;, check_commission(input))

	input = &quot;15&quot;
	fmt.Println(&quot;\nInput value:&quot;, input)
	fmt.Println(&quot;Output value:&quot;, check_commission(input))

	input = &quot;2.3&quot;
	fmt.Println(&quot;\nInput value:&quot;, input)
	fmt.Println(&quot;Output value:&quot;, check_commission(input))
}

The function checks the input value for correctness.
The point is that the size of the commission can be from 0 to 99.99. Maximum number of decimal places: 2.
Only integer values can return from a function, so the comma has to be shifted by 2 characters.
For example, for a commission of 1.5, the return value will be 150. And if 15, then 15 will return.

How to fix this function correctly? Link to play go.

答案1

得分: 1

uint64(tempValue)替换为uint64(math.Round(tempValue))

play.golang.org上运行程序。

然而,正如评论中提到的那样,我对使用浮点数表示货币持非常谨慎的态度。我认为你可能需要一个"decimal"类型(例如,shopspring.decimal,正如你上面提到的)。

英文:

Replace uint64(tempValue) with uint64(math.Round(tempValue)).

Running program at play.golang.org

However I would be quite wary of using float for money, as mentioned in the comments. I think you might want a "decimal" type (e.g., shopspring.decimal, as you asked above)

huangapple
  • 本文由 发表于 2021年8月7日 03:43:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/68686799.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定