Golang – 如何将指数和尾数转换为 float64 或 float32

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

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包是使用float32float64的一个很好的替代方案。然而,它并没有提供一个指数函数。一个提供指数函数的包是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.

huangapple
  • 本文由 发表于 2022年9月12日 00:09:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/73680755.html
匿名

发表评论

匿名网友

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

确定