数字/人民币互转

一、数字转人民币

package main

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

var (
	// 数字对应的大写中文
	digits = []string{"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}
	// 整数部分的单位
	units = []string{"", "拾", "佰", "仟"}
	// 小数部分的单位
	decimalUnits = []string{"分", "角"}
)

// ConvertToRMB 将数字转换为大写人民币格式
func ConvertToRMB(num float64) string {
	if num == 0 {
		return "零元整"
	}

	// 分离整数和小数部分
	integerPart := int64(num)
	decimalPart := int64(math.Round((num - float64(integerPart)) * 100))

	// 处理整数部分
	integerStr := convertInteger(integerPart)
	// 处理小数部分
	decimalStr := convertDecimal(decimalPart)
	// 拼接结果
	result := integerStr + "元"
	if decimalStr == "" {
		result += "整"
	} else {
		result += decimalStr
	}
	return result
}

// convertInteger 转换整数部分
func convertInteger(num int64) string {
	if num == 0 {
		return "零"
	}
	var resultArr []string
	var tmp string
	unitIndex := 0
	for num > 0 {
		digit := num % 10
		if digit != 0 {
			tmp = digits[digit] + units[unitIndex] + tmp
		} else {
			// 处理零的情况(避免连续多个零)
			if tmp != "" && !strings.HasPrefix(tmp, "零") {
				tmp = digits[digit] + tmp
			}
		}
		num /= 10
		unitIndex++

		if unitIndex%4 == 0 {
			resultArr = append(resultArr, tmp)
			tmp = ""
			unitIndex = 0
		}
	}
	if len(tmp) > 0 {
		resultArr = append(resultArr, tmp)
	}
	var result string
	for i := len(resultArr) - 1; i >= 0; i-- {
		if i == 2 {
			result += resultArr[i] + "亿"
		} else if i == 1 {
			result += resultArr[i] + "万"
		} else if i == 0 {
			result += resultArr[i]
		}
	}
	return result
}

// convertDecimal 转换小数部分
func convertDecimal(num int64) string {
	if num == 0 {
		return ""
	}

	var result string
	for i := 0; i < len(decimalUnits) && num > 0; i++ {
		digit := num % 10
		if digit != 0 {
			result = digits[digit] + decimalUnits[i] + result
		}
		num /= 10
	}

	return result
}

func main() {
	testCases := []float64{
		0,
		0.5,
		123.45,
		1000.51,
		1001.50,
		1020.50,
		1021.50,
		1201.52,
		10000.50,
		123456789.99,
	}

	for _, num := range testCases {
		fmt.Printf("%.2f -> %s\n", num, ConvertToRMB(num))
	}
}

二、人民币转数字

步骤如下:

  1. 我们从左到右读取每个字符,如果是数字就先记下来,如果是单位就将记下来的数组乘以相应的倍数加到总和中。如五百三十六=(500)+(30)+6。但对于后面带万和亿的上面情况显然不符合。例如五百三十六万六千零三,按照上面计算方法为(500)+(30)+(60000),其实正确的做法应该是(500+30+6)*10000才对。

  2. 对于遇到“万”的情况,如五百三十六万六千零三,正确的拆分方式为:(五百三十六)万(六千零三)

  3. 同理对于遇到“亿”的情况,如一百二十亿三千三百八十三万六百六十六,正确的拆分方式为:(一百二十)亿(三千三百八十三)万(六百六十六)

  4. 特别的对于“万亿”也应该处理,如(二)万亿(零三千三百八十三)万(零六百六十六)

  5. 最后将上述每个“万”、“亿”、“万亿”分割的部分乘以相应的单位加到累加和中

举个栗子:

// 五百三十六万六千零三
// (一百二十)亿(三千三百八十三)万(零六百六十六)
// (三千三百八十三)万(零六百六十六)
// (六十六)万
//(二)万亿(零三千三百八十三)万(零六百六十六)

实现代码:

package main

import "fmt"

var CNNumbers = map[rune]int{'零': 0, '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9}
var CNUnits = map[rune]int{'零': 1, '十': 10, '百': 100, '千': 1000, '万': 10000, '亿': 100000000}

// 五百三十六万六千零三
// (一百二十)亿(三千三百八十三)万(零六百六十六)
// (三千三百八十三)万(零六百六十六)
// (六十六)万
//(二)万亿(零三千三百八十三)万(零六百六十六)

func rmbToInt(numStr string) int {
	res := 0
	l, r := 0, 0
	numStrs := []rune(numStr)
	for r < len(numStrs) {
		if numStrs[r] == '亿' {
			res += _rmbToInt(string(numStrs[l:r])) * CNUnits['亿']
			l = r + 1
		} else if numStrs[r] == '万' {
			if r+1 < len(numStrs) && numStrs[r+1] == '亿' {
				res += _rmbToInt(string(numStrs[l:r])) * CNUnits['万'] * CNUnits['亿']
				r = r + 1
				l = r + 1
			} else {
				res += _rmbToInt(string(numStrs[l:r])) * CNUnits['万']

				l = r + 1
			}
		}
		r++
		//fmt.Println("part:", l, r, numStr+":", res)
	}

	if l < r {
		res += _rmbToInt(string(numStrs[l:r]))
	}
	fmt.Println(numStr+":", res)
	return res
}
func _rmbToInt(numStr string) int {
	res := 0
	//和的每一部分
	section := 0
	for _, ch := range []rune(numStr) {
		if digit, ok := CNNumbers[ch]; ok { //数字
			section = digit
		} else { //单位
			if unit, ok := CNUnits[ch]; ok {
				section *= unit
				res += section
				section = 0
			}
		}
	}
	res += section
	//fmt.Println("part:", numStr, res)
	return res
}
func main() {
	rmbToInt("三千三百八十三万零六百六十六")
	rmbToInt("六十六万")
	rmbToInt("三千三百八十三万")
	//rmbToInt("一百二十亿三千三百八十三万零六百六十六")
	rmbToInt("二万亿三千三百八十三万零六百六十六")
	rmbToInt("二万亿")
	rmbToInt("一百万亿三千三百八十三万零六百六十六元")
	rmbToInt("一百万亿三千三百八十三万零六百六十六元")
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值