From 61df3fd304a7734396d36233db4d5768e32012de Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 02:54:52 +0000 Subject: [PATCH] fix(numbers): round decimal carry correctly Co-Authored-By: Virgil --- numbers.go | 5 +++++ numbers_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/numbers.go b/numbers.go index c58cc44..551844e 100644 --- a/numbers.go +++ b/numbers.go @@ -56,6 +56,11 @@ func FormatDecimalN(f float64, decimals int) string { } multiplier := math.Pow(10, float64(decimals)) fracInt := int64(math.Round(fracPart * multiplier)) + if fracInt >= int64(multiplier) { + intPart++ + intStr = formatIntWithSep(intPart, nf.ThousandsSep) + fracInt = 0 + } if fracInt == 0 { if negative { return "-" + intStr diff --git a/numbers_test.go b/numbers_test.go index 19bc525..1b20313 100644 --- a/numbers_test.go +++ b/numbers_test.go @@ -44,6 +44,8 @@ func TestFormatDecimal(t *testing.T) { }{ {1.5, "1.5"}, {1.0, "1"}, + {1.995, "2"}, + {9.999, "10"}, {1234.56, "1,234.56"}, {0.1, "0.1"}, {-0.1, "-0.1"}, @@ -58,6 +60,31 @@ func TestFormatDecimal(t *testing.T) { } } +func TestFormatDecimalN_RoundsCarry(t *testing.T) { + svc, err := New() + if err != nil { + t.Fatalf("New() failed: %v", err) + } + SetDefault(svc) + + tests := []struct { + f float64 + decimals int + want string + }{ + {1.995, 2, "2"}, + {9.999, 2, "10"}, + {999.999, 2, "1,000"}, + } + + for _, tt := range tests { + got := FormatDecimalN(tt.f, tt.decimals) + if got != tt.want { + t.Errorf("FormatDecimalN(%v, %d) = %q, want %q", tt.f, tt.decimals, got, tt.want) + } + } +} + func TestFormatPercent(t *testing.T) { svc, err := New() if err != nil { -- 2.45.3