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

Language agnostic 根据大小使用可变有效数字量格式化数字,language-agnostic,lua,formatting,format,Language Agnostic,Lua,Formatting,Format,我有一个小函数,它显示一些数值的格式化量。其目的是根据数字的大小显示重要数字的“常识”数量。例如,1234显示为1.2k,12345显示为12k,123456显示为123k 换句话说,我想在给定数量级的低端显示一个小数点,但对于较大的值,它只是无用的噪声 我需要这个函数从10亿一直扩展到几十亿。当前的解决方案只是将其分支: -- given `current` local text = ( current > 9,999,999,999 and ('%dB') :format(cur

我有一个小函数,它显示一些数值的格式化量。其目的是根据数字的大小显示重要数字的“常识”数量。例如,1234显示为1.2k,12345显示为12k,123456显示为123k

换句话说,我想在给定数量级的低端显示一个小数点,但对于较大的值,它只是无用的噪声

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

-- given `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)  -- show values < 1000 floored
)
textobject:SetText(text)

-- code formatted for readability
——给定“当前”`
本地文本=(
当前>999999999和(“%dB”):格式(当前/100000000)或
当前>99999999和('%.1fB'):格式(当前/100000000)或
当前>999999和(“%dM”):格式(当前/1000000)或
当前>999999和('%.1fM'):格式(当前/1000000)或
当前>9999和(“%dk”):格式(当前/1000)或
当前>999和('%.1fk'):格式(当前/1000)或
(“%d”):格式(当前)--显示小于1000的值
)
textobject:SetText(文本)
--为可读性而格式化的代码

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

将范围及其后缀放在一张表中

local multipliers = {
  {10^10, 'B', 10^9},
  {10^9, 'B', 10^9, true},
  {10^7, 'M', 10^6},
  {10^6, 'M', 10^6, true},
  {10^4, 'k', 10^3},
  {10^3, 'k', 10^3, true},
  {1, '', 1},
}
备选变量第4位的可选
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

直到一位朋友给了我一个解决方案(根据长度检查数字的大小),我才意识到这有多么简单。我将其转换为使用log来查找震级,现在有了一个优雅的工作答案:

local suf = {'k','M','B','T'}
local function clean_format(val)
  if val == 0 then return '0' end  -- *Edit*: Fix an error caused by attempting to get log10(0)
  local m = math.min(#suf,math.floor(math.log10(val)/3))  -- find the magnitude, or use the max magnitude we 'understand'
  local n = val / 1000 ^ m                                -- calculate the displayed value
  local fmt = (m == 0 or n >= 10) and '%d%s' or '%.1f%s'  -- and choose whether to apply a decimal place based on its size and magnitude
  return fmt:format(n,suf[m] or '')
end
将其放大以支持更大的1000倍,就像将下一个条目放入
suf
数组一样简单


注意:出于语言无关的目的,Lua数组是基于1的,而不是基于零的。上述解决方案会在许多其他语言中出现一个接一个的错误

这个问题似乎离题了,因为它是关于虽然这看起来应该有效,但它本质上与我在上面采用的方法相同,只是通过编程完成的。它同样丑陋,因为我需要不断向表中添加新行以解决放大问题。它的效率也不是很高。