Browse Source

feat: 迁移金额字符串求和方法 MoneyAdd

wangkang 1 week ago
parent
commit
68ca1b4e01
2 changed files with 74 additions and 0 deletions
  1. 52 0
      common/amount.go
  2. 22 0
      common/amount_test.go

+ 52 - 0
common/amount.go

@@ -53,3 +53,55 @@ func normalizeAmount(amount string) string {
 func MoneyNormalize(s string) string {
 	return strings.ReplaceAll(s, ",", "")
 }
+
+// 金额字符串求和,要求金额字符串必须是整数且保留两位小数。
+func MoneyAdd(a, b string) string {
+	// n = max(len(a), len(b))
+	var n int
+	if len(a) > len(b) {
+		n = len(a)
+	} else {
+		n = len(b)
+	}
+
+	// 倒序求和
+	//  123.45
+	// + 67.89
+	// --------
+	// _191.34
+	bs := make([]byte, n+1) // 可能有进位
+	var carry byte
+	for i := 1; i <= n; i++ {
+		// 小数点
+		if i == 3 {
+			bs[n-i+1] = '.'
+			continue
+		}
+
+		// 和 算数值
+		c := byteOf(a, i) + byteOf(b, i) + carry
+		if c >= 10 {
+			carry = 1
+			c -= 10
+		} else {
+			carry = 0
+		}
+		bs[n-i+1] = c + '0'
+	}
+	if carry != 0 {
+		bs[0] = '1'
+		return string(bs)
+	}
+	return string(bs[1:])
+}
+
+// 倒取字符串对应位算数值,超长取 0。
+//
+//	byteOf("123.45", 1) -> 5
+//	byteOf("67.89", 5) -> 0
+func byteOf(s string, i int) byte {
+	if len(s) < i {
+		return 0
+	}
+	return s[len(s)-i] - '0'
+}

+ 22 - 0
common/amount_test.go

@@ -115,6 +115,11 @@ func TestIsAmountEqual(t *testing.T) {
 			amount2: "0",
 			want:    true,
 		},
+		{
+			amount1: "0",
+			amount2: "",
+			want:    true,
+		},
 		{
 			amount1: "0",
 			amount2: "0.00",
@@ -139,3 +144,20 @@ func TestIsAmountEqual(t *testing.T) {
 		}
 	}
 }
+
+func TestMoneyAdd(t *testing.T) {
+	for _, tc := range []struct {
+		a, b, want string
+	}{
+		{"123.45", "67.89", "191.34"},
+		{"9.00", "1.00", "10.00"},
+		{"0.10", "0.20", "0.30"},
+		{"1.23", "1.23", "2.46"},
+		{"0.00", "0.00", "0.00"},
+	} {
+		r := MoneyAdd(tc.a, tc.b)
+		if r != tc.want {
+			t.Errorf("Expected %v, but got %v", tc.want, r)
+		}
+	}
+}