Go语言的浮点型比较大小、与字符串互转、精准舍入

我们在编程中经常需要对两个浮点型比较大小,下面我就来分享一段这样的代码,同时也展示了Go语言函数式编程的独特魅力:

import (
	"fmt"
	"math"
)

func main() {
	// 设置精确度为0.00001
	var a Accuracy = func() float64 { return 0.00001 }
	fmt.Println(a.Equal(0.11111222, 0.11111222233333)) //打印结果为:true
}

type Accuracy func() float64

func (this Accuracy) Equal(a, b float64) bool {
	return math.Abs(a-b) < this()
}

func (this Accuracy) Greater(a, b float64) bool {
	return math.Max(a, b) == a && math.Abs(a-b) > this()
}

func (this Accuracy) Smaller(a, b float64) bool {
	return math.Max(a, b) == b && math.Abs(a-b) > this()
}

func (this Accuracy) GreaterOrEqual(a, b float64) bool {
	return math.Max(a, b) == a || math.Abs(a-b) < this()
}

func (this Accuracy) SmallerOrEqual(a, b float64) bool {
	return math.Max(a, b) == b || math.Abs(a-b) < this()
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

再来分享一个较完整的处理浮点数的结构体——Floater

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

type Floater struct {
	numOfDecimalPlaces int
	accuracy           float64
	format             string
}

func NewFloater(numOfDecimalPlaces int) *Floater {
	if numOfDecimalPlaces < 0 || numOfDecimalPlaces > 14 {
		panic("the range of Floater.numOfDecimalPlaces must be between 0 and 14.")
	}
	var accuracy float64 = 1
	if numOfDecimalPlaces > 0 {
		accuracyString := "0." + strings.Repeat("0", numOfDecimalPlaces-1) + "1"
		accuracy, _ = strconv.ParseFloat(accuracyString, 64)
	}
	return &Floater{
		numOfDecimalPlaces: numOfDecimalPlaces,
		accuracy:           accuracy,
		format:             "%0." + strconv.Itoa(numOfDecimalPlaces) + "f",
	}
}

func (this *Floater) NumOfDecimalPlaces() int {
	return this.numOfDecimalPlaces
}

func (this *Floater) Accuracy() float64 {
	return this.accuracy
}

func (this *Floater) Format() string {
	return this.format
}

func (this *Floater) Ftoa(f float64) string {
	return fmt.Sprintf(this.format, f)
}

func (this *Floater) Atof(s string, bitSize int) (float64, error) {
	f, err := strconv.ParseFloat(s, bitSize)
	if err != nil {
		return f, err
	}
	return strconv.ParseFloat(fmt.Sprintf(this.format, f), bitSize)
}

func (this *Floater) Ftof(f float64) float64 {
	f, _ = strconv.ParseFloat(fmt.Sprintf(this.format, f), 64)
	return f
}

func (this *Floater) Atoa(s string, bitSize int) (string, error) {
	f, err := strconv.ParseFloat(s, bitSize)
	if err != nil {
		return s, err
	}
	return fmt.Sprintf(this.format, f), nil
}

func (this *Floater) Equal(a, b float64) bool {
	return math.Abs(a-b) < this.accuracy
}

func (this *Floater) Greater(a, b float64) bool {
	return math.Max(a, b) == a && math.Abs(a-b) > this.accuracy
}

func (this *Floater) Smaller(a, b float64) bool {
	return math.Max(a, b) == b && math.Abs(a-b) > this.accuracy
}

func (this *Floater) GreaterOrEqual(a, b float64) bool {
	return math.Max(a, b) == a || math.Abs(a-b) < this.accuracy
}

func (this *Floater) SmallerOrEqual(a, b float64) bool {
	return math.Max(a, b) == b || math.Abs(a-b) < this.accuracy
}

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券