根据大小使用可变数量的有效数字格式化数字。

我有一个小函数,用于显示格式化的某个数字值的金额。意图是根据数字的大小显示“常识”数量的有效数字。因此,例如,1,234显示为1.2k,而12,345显示为12k,123,456显示为123k。

换句话说,我希望在给定数量级的低端显示一个小数,但对于更大的值,这只是无用的噪音。

我需要这个函数从1扩展到几十亿。目前的解决方案只是将其分支:

-- 假设 `current` 是现有的数字
local text = (
  current > 9,999,999,999 and ('%dB')  :format(current/1,000,000,000) or
  current >   999,999,999 and ('%.1fB'):format(current/1,000,000,000) or
  current >     9,999,999 and ('%dM')  :format(current/1,000,000) or
  current >       999,999 and ('%.1fM'):format(current/1,000,000) or
  current >         9,999 and ('%dk')  :format(current/1,000) or
  current >           999 and ('%.1fk'):format(current/1,000) or
  ('%d'):format(current)  -- 显示值小于1000个数字
)
textobject:SetText(text)

-- 代码格式化以便阅读

我觉得这很丑陋。是否有一些优雅的公式可以以这种方式四舍五入数字,而不仅仅是为每个我需要支持的1000个因数添加另一个(两个)子句?

点赞
用户1190388
用户1190388

将您的范围及其后缀放入表格中。

local multipliers = {
  {10^10'B'10^9},
  {10^9'B'10^9true},
  {10^7'M'10^6},
  {10^6'M'10^6true},
  {10^4'k'10^3},
  {10^3'k'10^3true},
  {1''1},
}

替代变量的第四个位置上的可选true值用于%.1f占位符。第三个索引是除数。

现在,使用ipairs遍历此表格并相应地格式化:

function MyFormatter( current )
    for i, t in ipairs( multipliers ) do
      if current >= t[1] then
        local sHold = (t[4] and "%.1f" or "%d")..t[2]
        return sHold:format( current/t[3] )
      end
    end
end
2014-08-16 03:12:20
用户3946218
用户3946218

在一位朋友给我一个解决方案之前,我并没有意识到这有多简单(该解决方案基于数字的长度检查其数量级)。我将其转化为使用对数来找到数量级,并且现在有了一个优美的工作答案:

local suf = {'k','M','B','T'}
local function clean_format(val)
  if val == 0 then return '0' end  -- *编辑*:修复尝试获取log10(0)引起的错误
  local m = math.min(#suf,math.floor(math.log10(val)/3))  -- 找到数量级,或者使用我们“理解”的最大数量级
  local n = val / 1000 ^ m                                -- 计算显示的值
  local fmt = (m == 0 or n >= 10) and '%d%s' or '%.1f%s'  -- 根据其大小和数量级选择是否应用小数点
  return fmt:format(n,suf[m] or '')
end

将其扩展以支持更大的 1000 倍因子就像在 suf 数组中添加下一个条目一样容易。

注意:为了通用性,Lua 数组是从 1 开始的,而不是从 0 开始的。上述解决方案在许多其他语言中会出现一个一位的错误。

2014-08-16 03:15:05