赞 | 342 |
VIP | 10 |
好人卡 | 8 |
积分 | 262 |
经验 | 235776 |
最后登录 | 2024-9-23 |
在线时间 | 2387 小时 |
Lv5.捕梦者 (版主) 遠航の猫咪
- 梦石
- 3
- 星屑
- 23209
- 在线时间
- 2387 小时
- 注册时间
- 2005-10-15
- 帖子
- 1166
|
本帖最后由 SailCat 于 2024-9-1 02:21 编辑
不建议使用除以1000.0, 10000.0这样的操作
原因是1000.0这个数字没办法精确保存,简单的办法是to_s后,直接切字符串
随手写了一个,没仔细测
# 用英文表示(千进制)配置第一行,中文表示(万进制)配置第二行 EXP_WORDS = ["", "K", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"] # EXP_WORDS = ["", "万", "亿", "兆", "京", "垓", "秭", "穰", "沟", "涧"] # 用英文表示(千进制)配置第一行,中文表示(万进制)配置第二行 EXP_SIZE = 3 # EXP_SIZE = 4 # 最小位数,不到此位数会降级显示(如设为2,23000会显示为23000而不是2万) MIN_DIGITS = 1 # 小数点后有效数字(12.0的0有意义,转换会保留) DECIMALS = 0 #-------------------------------------------------------------------------- # ● 转换大数字的显示位数 # x : 要转换的数字,必须是整数(Fixnum/Bignum),可正可负 # method : 舍入处理规则,合法取值有5个 # "round" : 四舍五入(默认)1.4=>1 1.5=>2 -1.4=>-1 -1.5=>-2 # "ceil" : 向上取整 1.4=>2 1.5=>2 -1.4=>-1 -1.5=>-1 # "floor" : 向下取整 1.4=>1 1.5=>1 -1.4=>-2 -1.5=>-2 # "trunc" : 向内取整 1.4=>1 1.5=>1 -1.4=>-1 -1.5=>-1 # "away" : 向外取整 1.4=>2 1.5=>2 -1.4=>-2 -1.5=>-2 # (写成不是另外四种取值的字符串,都会以"round"处理) #-------------------------------------------------------------------------- def convert_number(x, method = "round") # 负数前置处理 neg = x < 0 # 字符串度量化 str = x.abs.to_s len = str.length exp = (len - MIN_DIGITS) / EXP_SIZE delimit = exp * EXP_SIZE # 小数点前截取 before = str[0..-delimit - 1].to_i # 小数点后截取 after = delimit > 0 ? str[-delimit, DECIMALS].to_i : 0 # 进位处理 if delimit > DECIMALS round = str[-delimit + DECIMALS, 1].to_i case round when 0 carry = (method == (neg ? "floor" : "ceil") || method == "away") && str[-delimit + DECIMALS + 1..-1].to_i == 0 when 1..4 carry = (method == (neg ? "floor" : "ceil") || method == "away") when 5..9 carry = (method != (neg ? "ceil" : "floor") && method != "trunc") end if carry after += 1 if after == 10 ** DECIMALS before += 1 after = 0 end end end # 按有无小数点分别输出 if DECIMALS > 0 and delimit > 0 digits = [DECIMALS, delimit].min result = sprintf("%d.%0#{digits}d%s", before, after, EXP_WORDS[exp]) else result = sprintf("%d%s", before, EXP_WORDS[exp]) end # 负数后置处理,返回 return neg ? "-" + result : result end
# 用英文表示(千进制)配置第一行,中文表示(万进制)配置第二行
EXP_WORDS = ["", "K", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"]
# EXP_WORDS = ["", "万", "亿", "兆", "京", "垓", "秭", "穰", "沟", "涧"]
# 用英文表示(千进制)配置第一行,中文表示(万进制)配置第二行
EXP_SIZE = 3
# EXP_SIZE = 4
# 最小位数,不到此位数会降级显示(如设为2,23000会显示为23000而不是2万)
MIN_DIGITS = 1
# 小数点后有效数字(12.0的0有意义,转换会保留)
DECIMALS = 0
#--------------------------------------------------------------------------
# ● 转换大数字的显示位数
# x : 要转换的数字,必须是整数(Fixnum/Bignum),可正可负
# method : 舍入处理规则,合法取值有5个
# "round" : 四舍五入(默认)1.4=>1 1.5=>2 -1.4=>-1 -1.5=>-2
# "ceil" : 向上取整 1.4=>2 1.5=>2 -1.4=>-1 -1.5=>-1
# "floor" : 向下取整 1.4=>1 1.5=>1 -1.4=>-2 -1.5=>-2
# "trunc" : 向内取整 1.4=>1 1.5=>1 -1.4=>-1 -1.5=>-1
# "away" : 向外取整 1.4=>2 1.5=>2 -1.4=>-2 -1.5=>-2
# (写成不是另外四种取值的字符串,都会以"round"处理)
#--------------------------------------------------------------------------
def convert_number(x, method = "round")
# 负数前置处理
neg = x < 0
# 字符串度量化
str = x.abs.to_s
len = str.length
exp = (len - MIN_DIGITS) / EXP_SIZE
delimit = exp * EXP_SIZE
# 小数点前截取
before = str[0..-delimit - 1].to_i
# 小数点后截取
after = delimit > 0 ? str[-delimit, DECIMALS].to_i : 0
# 进位处理
if delimit > DECIMALS
round = str[-delimit + DECIMALS, 1].to_i
case round
when 0
carry = (method == (neg ? "floor" : "ceil") || method == "away") &&
str[-delimit + DECIMALS + 1..-1].to_i == 0
when 1..4
carry = (method == (neg ? "floor" : "ceil") || method == "away")
when 5..9
carry = (method != (neg ? "ceil" : "floor") && method != "trunc")
end
if carry
after += 1
if after == 10 ** DECIMALS
before += 1
after = 0
end
end
end
# 按有无小数点分别输出
if DECIMALS > 0 and delimit > 0
digits = [DECIMALS, delimit].min
result = sprintf("%d.%0#{digits}d%s", before, after, EXP_WORDS[exp])
else
result = sprintf("%d%s", before, EXP_WORDS[exp])
end
# 负数后置处理,返回
return neg ? "-" + result : result
end
|
|