英文:
Golang - How to turn an exponent and mantissa to a float64 or float32
问题
我有一个库,可以提供浮点数的尾数和指数值,以保证不丢失精度。
尾数:375400000000000
指数:-9
在golang中,我该如何将其转换为float32或float64?
我在这里尝试了一下,但是得到的数字明显不正确:https://go.dev/play/p/8wMxhq11qwS
package main
import (
"fmt"
"math/big"
)
func main() {
mantissa := 375600000000000
exp := int8(-9)
var price big.Float
mant := big.NewFloat(float64(mantissa))
price.SetMantExp(mant, int(exp))
fmt.Println("price: ", price.String())
fmt.Println("mant: ", mantissa)
fmt.Println("exp: ", exp)
}
显然这不起作用,因为big.Float的表示方式是sign × mantissa × 2**exponent
,而我需要的是sign × mantissa × 10^exp
。
英文:
I have a library that gives floats in mantissa and exponent values for no loss of precision.
Mantissa: 375400000000000
Exponent: -9
How do I turn this into a float32 or float64 in golang?
I gave it a shot here but the number is definitely not coming out correctly: https://go.dev/play/p/8wMxhq11qwS
package main
import (
"fmt"
"math/big"
)
func main() {
mantissa := 375600000000000
exp := int8(-9)
var price big.Float
mant := big.NewFloat(float64(mantissa))
price.SetMantExp(mant, int(exp))
fmt.Println("price: ", price.String())
fmt.Println("mant: ", mantissa)
fmt.Println("exp: ", exp)
}
Apparently this doesn't work because big.Float is represented by sign × mantissa × 2**exponent
when I need sign x mantissa x 10 ^ exp
答案1
得分: 3
我认为最明显的解决方案是使用数学包中的Pow10
函数:
package main
import (
"fmt"
"math"
)
func main() {
mantissa := 375600000000000
exp := int8(-9)
price := float64(mantissa) * math.Pow10(int(exp))
fmt.Println("价格:", price)
fmt.Println("尾数:", mantissa)
fmt.Println("指数:", exp)
}
这个函数对于指数的所有可能值都是有效的,但是精度可能会因尾数的值而降低。
英文:
I think the most obvious solution would be to use the Pow10
function in the math package:
package main
import (
"fmt"
"math"
)
func main() {
mantissa := 375600000000000
exp := int8(-9)
price := float64(mantissa) * math.Pow10(int(exp))
fmt.Println("price: ", price)
fmt.Println("mant: ", mantissa)
fmt.Println("exp: ", exp)
}
This function is valid for all possible values of your exponent, but precision may be degraded depending on the value of your mantissa.
答案2
得分: 1
作为一个在Go中经常遇到精度问题的人,math/big
包是使用float32
或float64
的一个很好的替代方案。然而,它并没有提供一个指数函数。一个提供指数函数的包是ericlagergren/decimal:
package main
import (
"fmt"
"github.com/ericlagergren/decimal"
)
func main() {
mantissa := decimal.New(375600000000000, 0)
exp := decimal.New(-9, 0)
ctx := decimal.Context {
Precision: 9, // 设置这个来确定期望的小数位数
}
price := new(decimal.Big)
ctx.Pow(price, decimal.New(10, 0), exp).Mul(price, mantissa)
fmt.Println("price: ", price)
fmt.Println("mant: ", mantissa)
fmt.Println("exp: ", exp)
}
这个包的好处是结果保证符合设置的精度。缺点是你必须显式地设置精度。在这个例子中,我设置了9位数字的精度,因为中间计算会得到一个输出为1e-9
的结果,需要9位精度。
英文:
As someone who's had to deal with precision issues in Go quite a bit, the math/big
package is an excellent alternative to using float32
or float64
. However, it does not offer an exponentiation function. One package that does is ericlagergren/decimal:
package main
import (
"fmt"
"github.com/ericlagergren/decimal"
)
func main() {
mantissa := decimal.New(375600000000000, 0)
exp := decimal.New(-9, 0)
ctx := decimal.Context {
Precision: 9, // Set this to determine the number of expected decimal places
}
price := new(decimal.Big)
ctx.Pow(price, decimal.New(10, 0), exp).Mul(price, mantissa)
fmt.Println("price: ", price)
fmt.Println("mant: ", mantissa)
fmt.Println("exp: ", exp)
}
The upside to this package is that the result is guaranteed to the set precision. The downside is that you have to set that precision explicitly. In this example, I set a precision of 9 digits because an interim calculation would result in an output of 1e-9
, which requires 9 digits of precision.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论