英文:
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")
来实例化十进制数,测试就会通过。我的问题是:为什么NewFromString
和NewFromFloat
的底层值不同?
英文:
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
我想补充一点,没有必要急着去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
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论