From b5caa67436f131081606f4cdf8beb38ee26374bf Mon Sep 17 00:00:00 2001 From: nipuna Date: Fri, 21 Jun 2024 12:21:55 +0200 Subject: [PATCH 1/2] math.Pow10 performance upgrade --- gofloat.go | 62 +++++++++++++++++++++++++++++-------------------- gofloat_test.go | 13 +++++++---- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/gofloat.go b/gofloat.go index 57cf10e..30ccae6 100644 --- a/gofloat.go +++ b/gofloat.go @@ -7,71 +7,83 @@ import ( // Float is to keep float's integer value, decimal value and its precision type Float struct { - integer int64 - decimal int64 - precision int + integer int64 + decimal int64 + precision int + precisionFactor int64 } // ToFloat returns a Float of f to given precision func ToFloat(f float64, precision int) Float { - floatingLength := int64(math.Trunc(math.Pow(10, float64(precision)))) - rounded := math.Round(f * float64(floatingLength)) + precision = int(math.Abs(float64(precision))) + floatingLength := math.Pow10(precision) + return toFloat(f, precision, int64(floatingLength)) +} + +func toFloat(f float64, precision int, precisionFactor int64) Float { + rounded := math.Round(f * float64(precisionFactor)) return Float{ - integer: int64(rounded) / floatingLength, - decimal: int64(rounded) % floatingLength, - precision: precision, + integer: int64(rounded) / precisionFactor, + decimal: int64(rounded) % precisionFactor, + precision: precision, + precisionFactor: precisionFactor, } } // Add returns a Float of f + x func (f Float) Add(x Float) Float { - max := getMaxPrecision(f.precision, x.precision) + maxP, maxFact := getMaxPrecision(f, x) sum := f.Float64() + x.Float64() - return ToFloat(sum, max) + return toFloat(sum, maxP, maxFact) } // Sub returns a Float of f - x func (f Float) Sub(x Float) Float { - max := getMaxPrecision(f.precision, x.precision) + maxP, maxFact := getMaxPrecision(f, x) sub := f.Float64() - x.Float64() - return ToFloat(sub, max) + return toFloat(sub, maxP, maxFact) } // Multiply returns a Float of f * x func (f Float) Multiply(x Float) Float { - max := getMaxPrecision(f.precision, x.precision) + maxP, maxFact := getMaxPrecision(f, x) mul := f.Float64() * x.Float64() - return ToFloat(mul, max) + return toFloat(mul, maxP, maxFact) } // Divide returns a Float of f / x // // Special cases are : -// x.Float64 = 0 returns Float value 0 +// +// x.Float64 = 0 returns Float value 0 func (f Float) Divide(x Float) Float { if x.Float64() == 0 { - return ToFloat(0, 0) + return Float{ + integer: 0, + decimal: 0, + precision: f.precision, + precisionFactor: f.precisionFactor, + } } - max := getMaxPrecision(f.precision, x.precision) + maxP, maxFact := getMaxPrecision(f, x) dev := f.Float64() / x.Float64() - return ToFloat(dev, max) + return toFloat(dev, maxP, maxFact) } // Float64 returns a float64 value of f func (f Float) Float64() float64 { - floatingLength := int64(math.Trunc(math.Pow(10, float64(f.precision)))) - return (float64(f.integer*floatingLength) + float64(f.decimal)) / float64(floatingLength) + return (float64(f.integer*f.precisionFactor) + float64(f.decimal)) / float64(f.precisionFactor) } func (f Float) String() string { return strconv.FormatFloat(f.Float64(), 'f', f.precision, 64) } -func getMaxPrecision(p1, p2 int) (max int) { - max = p1 - if p1 < p2 { - max = p2 +func getMaxPrecision(p1, p2 Float) (max int, maxFactor int64) { + if p1.precision < p2.precision { + return p2.precision, p2.precisionFactor } - return + + return p1.precision, p1.precisionFactor } diff --git a/gofloat_test.go b/gofloat_test.go index bd040c0..452258f 100644 --- a/gofloat_test.go +++ b/gofloat_test.go @@ -148,11 +148,14 @@ func setupTestTable(operator string) []TestInput { precision2: rand.Intn(9), } - length1 := math.Trunc(math.Pow(10, float64(inputs[i].precision1))) - max := getMaxPrecision(inputs[i].precision1, inputs[i].precision2) - lengthMax := math.Trunc(math.Pow(10, float64(max))) - rounded1 := ToFloat(inputs[i].input1, inputs[i].precision1).Float64() - rounded2 := ToFloat(inputs[i].input2, inputs[i].precision2).Float64() + length1 := math.Trunc(math.Pow10(inputs[i].precision1)) + + f1 := ToFloat(inputs[i].input1, inputs[i].precision1) + rounded1 := f1.Float64() + f2 := ToFloat(inputs[i].input2, inputs[i].precision2) + rounded2 := f2.Float64() + _, maxFact := getMaxPrecision(f1, f2) + lengthMax := float64(maxFact) switch operator { case `NONE`: From 99440b5250ea49c9ff55bf66b05525adcdb1f7d6 Mon Sep 17 00:00:00 2001 From: nipuna Date: Fri, 21 Jun 2024 12:22:46 +0200 Subject: [PATCH 2/2] fmt imports --- examples/usage/main.go | 3 ++- gofloat_example_test.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/usage/main.go b/examples/usage/main.go index 1655ae9..18cee79 100644 --- a/examples/usage/main.go +++ b/examples/usage/main.go @@ -2,8 +2,9 @@ package main import ( "fmt" - "github.com/senpathi/gofloat" "math" + + "github.com/senpathi/gofloat" ) func main() { diff --git a/gofloat_example_test.go b/gofloat_example_test.go index 4d63d48..3e0978e 100644 --- a/gofloat_example_test.go +++ b/gofloat_example_test.go @@ -2,8 +2,9 @@ package gofloat_test import ( "fmt" - "github.com/senpathi/gofloat" "math" + + "github.com/senpathi/gofloat" ) func ExampleToFloat() {