当前位置: 首页 > 知识库问答 >
问题:

用国际单位制将数字格式化为三个sig图

凌征
2023-03-14

我想用国际单位制将一个整数格式化为3位有效数字。例如:

1     => '1'
999   => '999'
1234  => '1.23k'
1235  => '1.24k'

下面是我对一个函数的粗略修改,仍然不能满足我的所有测试。我遇到的问题涉及检测何时9…将四舍五入到10…,因此需要在末尾少一个小数点。

tests = [[9,'9'],[1,'1'],[10,'10'],[99,'99'],[100,'100'],[999,'999'],
        [1000,'1.00k'],[1004,'1.00k'],[1009,'1.01k'],[1472,'1.47k'],
        [1926,'1.93k'],[1999,'2.00k'],[2000,'2.00k'],[9813,'9.81k'],
        [9990,'9.99k'],[9999,'10.0k'],[10000,'10.0k'],[10010,'10.0k'],
        [60712,'60.7k'],[98712,'98.7k'],[99949,'99.9k'],[99950,'100k'],
        [99999,'100k'],[100000,'100k'],[400499,'400k'],[999499,'999k'],
        [999500,'1.00M'],[999999,'1.00M'],[1000000,'1.00M'],
        [1234567,'1.23M'],[12345678,'12.3M'],[123456789,'123M']]

tests.forEach( ([n,expected]) => {
    const actual = siRound(n)
    console.log(n, actual, actual==expected ? '=' : '≠', expected)
})

function siRound(x) {
    if (x<1e3) return x+'';
    const digits = Math.log10(x) | 0
    const tier = digits/3 | 0
    let str = (x / 10**(tier*3)).toFixed(2-(digits%3))
    // Turn "10.00" into "10.0" and "100.0" into "100"
    str = str.replace(/^(.{3})\..+|^(.{4}).+/, '$1$2')
    return str + (['','k','M','G','T'])[tier]
}

共有3个答案

万高畅
2023-03-14

基于@HereticMonkey指出存在toPrecision(),这里有一个可行的答案,尽管我觉得有点恶心。如果有人发布了一个答案,我会把它换成一个更干净、完全有效的答案。

// Note: intentionally returns integers below 1,000 unchanged.
// For true precision across all numbers, remove the first line.
function siRound(n, precision=3) {
    if (x<1e3) return x+''
    let tier = Math.log10(x)/3 | 0
    let str = (x / 10**(tier*3)).toPrecision(precision)
    if (str>=1e3) str = (x / 10**(++tier*3)).toPrecision(precision)
    return str + (['','k','M','G','T','P','E','Z','Y'])[tier]
}
江天宇
2023-03-14
tests = [[9,'9'],[1,'1'],[10,'10'],[99,'99'],[100,'100'],[999,'999'],
        [1000,'1.00k'],[1004,'1.00k'],[1009,'1.01k'],[1472,'1.47k'],
        [1926,'1.93k'],[1999,'2.00k'],[2000,'2.00k'],[9813,'9.81k'],
        [9990,'9.99k'],[9999,'10.0k'],[10000,'10.0k'],[10010,'10.0k'],
        [60712,'60.7k'],[98712,'98.7k'],[99949,'99.9k'],[99950,'100k'],
        [99999,'100k'],[100000,'100k'],[400499,'400k'],[999499,'999k'],
        [999500,'1.00M'],[999999,'1.00M'],[1000000,'1.00M'],
        [1234567,'1.23M'],[12345678,'12.3M'],[123456789,'123M']]

const siRound = x => {
  if (x < 1e3) {
    return x;
  }
  let roudedX = x;
  let tier = 0;
  while (roudedX >= 1000) {
    roudedX /= 1000;
    tier += 1;
  }
  roudedX = Number.parseFloat(roudedX.toPrecision(3));
  if (Math.abs(roudedX - 1e3) < Number.EPSILON) {
    roudedX = 1;
    tier += 1;
  }
  return roudedX.toPrecision(3) + ['', 'k', 'M', 'G', 'T'][tier];
}

tests.forEach(([n,expected]) => {
  const actual = siRound(n)
  console.log(n, actual, actual==expected ? '=' : '≠', expected)
})
韩飞翮
2023-03-14

让你的方法像递归一样。添加此项,返回前检查:

if (str.length>4) { 
      siRound(str)
}
tests = [[9,'9'],[1,'1'],[10,'10'],[99,'99'],[100,'100'],[999,'999'],
        [1000,'1.00k'],[1004,'1.00k'],[1009,'1.01k'],[1472,'1.47k'],
        [1926,'1.93k'],[1999,'2.00k'],[2000,'2.00k'],[9813,'9.81k'],
        [9990,'9.99k'],[9999,'10.0k'],[10000,'10.0k'],[10010,'10.0k'],
        [60712,'60.7k'],[98712,'98.7k'],[99949,'99.9k'],[99950,'100k'],
        [99999,'100k'],[100000,'100k'],[400499,'400k'],[999499,'999k'],
        [999500,'1.00M'],[999999,'1.00M'],[1000000,'1.00M'],
        [1234567,'1.23M'],[12345678,'12.3M'],[123456789,'123M']]

tests.forEach( ([n,expected]) => {
    const actual = siRound(n)
    console.log(n, actual, actual==expected ? '=' : '≠', expected)
})

function siRound(x) {
    if (x<1e3) return x+'';
    const digits = Math.log10(x) | 0
    const tier = digits/3 | 0
    let str = (x / 10**(tier*3)).toFixed(2-(digits%3))
    // Turn "10.00" into "10.0" and "100.0" into "100"
    str = str.replace(/^(.{3})\..+|^(.{4}).+/, '$1$2')
    if (str.length>4) { ///Add this check
      siRound(str)
    }
    return str + (['','k','M','G','T'])[tier]
}
 类似资料:
  • 以下是在格式化模式中使用字符。 编号 类 描述 1 如果数字较小,则显示0。 2 显示忽略前导零的数字。 3 小数分隔符。 4 分组分隔符。 5 指数格式的尾数和指数分隔符。 6 格式分隔符。 7 负数字前缀。 8 将乘以100后的数字显示为百分比。 9 与1000相乘后显示数字为千位。 10 将字符标记为数字前缀/后缀。 11 标记特殊字符的引号。 在这个例子中,我们根据不同的模式来格式化数字。

  • 问题内容: 我想根据测量值打印字符串,但将其限制为2位数字。我为此使用 MeasurementFormatter 。 我期望结果不是。我的错在哪里 问题答案: 您需要将MeasurementFormatter属性unitOption设置为.providedUnit

  • 类提供了各种格式来格式化时间。 要使用方法。 看下面的例子。 在下面的例子中,我们将演示如何使用不同的格式来格式化时间。 文件:IOTester.java - 执行上面示例代码,得到以下结果 -

  • 类提供了各种格式来格式化日期。 以下是一些格式的列表。 在下面的例子中,我们将演示如何使用不同的格式。 文件:IOTester.java - 执行上面示例代码,得到以下结果 -

  • 在本例中,我们根据美国区域设置和丹麦语区域设置格式化货币。 文件:IOTester.java - 执行上面示例代码,得到以下结果 -

  • 使用 toLocaleString() 将浮点数转换为 Decimal mark 格式。 将整数部分转化为用逗号分隔的字符串。 const toDecimalMark = num => num.toLocaleString('en-US'); toDecimalMark(12305030388.9087); // "12,305,030,388.909"