github.com/shopspring/decimal:FromString和FromFloat产生不同的值

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

github.com/shopspring/decimal: different values produced by FromString and FromFloat

问题

我正在尝试使用gomock来模拟一个接受十进制数的接口。使用情况如下:

v, err := decimal.NewFromString(order.Value)
if err != nil {
    return err
}

if err := p.CDI.CreateBuyEvent(ctx, v); err != nil {
    return err
}

在测试中,我使用以下代码:

value := decimal.NewFromFloat64(1000)
cfg.cdi.EXPECT().CreateBuyEvent(ctx, value).Return(nil)

运行时,我得到以下错误信息:

expected call doesn't match the argument at index 1.
   Got: 1000 (entities.Order)
   Want: is equal to 1000 (entities.Order)

然而,如果我在测试中使用NewFromString("1000")来实例化十进制数,测试就会通过。我的问题是:为什么NewFromStringNewFromFloat的底层值不同?

英文:

I'm trying to use gomock to mock an interface that takes a decimal. The usecase:

v, err := decimal.NewFromString(order.Value)
if err != nil {
	return err
}

if err := p.CDI.CreateBuyEvent(ctx, v); err != nil {
	return err
}

And in the tests:

value := decimal.NewFromFloat64(1000)
cfg.cdi.EXPECT().CreateBuyEvent(ctx, value).Return(nil)

Running this, I get:

expected call doesn't match the argument at index 1.
   Got: 1000 (entities.Order)
   Want: is equal to 1000 (entities.Order)

However, if I instead instantiate the decimal using NewFromString("1000") in the tests, it passes. My question is: why is the underlying value different for NewFromString and NewFromFloat?

答案1

得分: 1

因为这两个值在逻辑上包含相同的值,但它们的内存表示不同。

使用Equal方法来比较shopspring.Decimal值。

示例代码:

package main

import (
	"fmt"

	"github.com/shopspring/decimal"
)

func main() {
	fs, err := decimal.NewFromString("1000")
	if err != nil {
		panic(err)
	}

	ff := decimal.NewFromFloat(1000)
	if ff != fs {
		fmt.Printf("%#v != %#v\n", fs, ff)
	}

	fmt.Println(ff.Equal(fs))
}

输出结果:

decimal.Decimal{value:(*big.Int)(0xc0001103a0), exp:0} != decimal.Decimal{value:(*big.Int)(0xc0001103c0), exp:3}
true

Playground


我想补充一点,没有必要急着去Stack Overflow上提问这样的问题:你应该先进行至少最基本的调试。
实际上,如果你有两个值,它们“必须”相同,但使用==运算符比较它们时不相等,这很愚蠢——它会逐个字段比较struct的值——那就看看这些值实际上包含了什么。

英文:

Because the two values happen to have different memory representations while logically containing the same values.

Use the Equal method to compare shopspring.Decimal values.

Demonstration:

package main

import (
	"fmt"

	"github.com/shopspring/decimal"
)

func main() {
	fs, err := decimal.NewFromString("1000")
	if err != nil {
		panic(err)
	}

	ff := decimal.NewFromFloat(1000)
	if ff != fs {
		fmt.Printf("%#v != %#v\n", fs, ff)
	}

	fmt.Println(ff.Equal(fs))
}

Produces:

decimal.Decimal{value:(*big.Int)(0xc0001103a0), exp:0} != decimal.Decimal{value:(*big.Int)(0xc0001103c0), exp:3}
true

Playground.


I would add that there's no need to rush for SO to ask a question like this: you should have first performed at least minimal debugging.
Really, if you have two values which must be the same but they do not compare equal using the == operator which is dumb — it compares struct vaues field-wise, — just see what the values actually contain.

huangapple
  • 本文由 发表于 2022年4月19日 22:21:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/71926549.html
匿名

发表评论

匿名网友

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

确定