我在下面尝试了示例代码
function sigFigs(n, sig) {
if ( n === 0 )
return 0
var mult = Math.pow(10,
sig - Math.floor(Math.log(n < 0 ? -n: n) / Math.LN10) - 1);
return Math.round(n * mult) / mult;
}
但是这个功能对输入不起作用 sigFigs(24730790,3)返回24699999.999999996 和sigFigs(4.7152e-26,3)返回:4.7200000000000004e-26
如果有人有工作示例请分享。 感谢。
答案 0 :(得分:5)
您可以尝试javascript内置方法 -
Number( my_number.toPrecision(3) )
对于您的案例,请尝试
Number( 24730790.0.toPrecision(5) )
对于您的参考和工作示例,您可以看到link
答案 1 :(得分:1)
不幸的是,当数字> 10时,例如指数符号等,内置方法会给您带来愚蠢的结果。
我做了一个函数,该函数应该可以解决问题(也许不是最优雅的编写方法,但是就可以了):
function(value, precision) {
if (value < 10) {
value = parseFloat(value).toPrecision(precision)
} else {
value = parseInt(value)
let significantValue = value
for (let i = value.toString().length; i > precision; i--) {
significantValue = Math.round(significantValue / 10)
}
for (let i = 0; significantValue.toString().length < value.toString().length; i++ ) {
significantValue = significantValue * 10
}
value = significantValue
}
return value
}
如果您希望对较大的数字使用指数表示法,请随时使用toPrecision()方法。
答案 2 :(得分:1)
首先感谢每个人,如果没有这些摘要共享,这将是一项艰巨的任务。
我的附加值是以下代码段(有关完整的实现,请参见下文)
parseFloat(number.toPrecision(precision))
请注意,如果数字是10000,而精度是2,则number.toPrecision(precision)
将是'1.0e + 4',但是parseFloat
会理解指数表示法。
无论是否相信,值得一提的是,在测试用例Math.pow
上运行时,使用formatNumber(5, 123456789)
和上面发布的对数的算法在Mac(节点v12)上运行成功,但是Windows(节点v10)上上升和错误。很奇怪,所以我们到达了上面的解决方案。
最后,我发现这是最终的实现,利用了本文中提供的所有反馈。假设我们有一个 formatNumber.js 文件,其中包含以下内容
/**
* Format number to significant digits.
*
* @param {Number} precision
* @param {Number} number
*
* @return {String} formattedValue
*/
export default function formatNumber (precision, number) {
if (typeof number === 'undefined' || number === null) return ''
if (number === 0) return '0'
const roundedValue = round(precision, number)
const floorValue = Math.floor(roundedValue)
const isInteger = Math.abs(floorValue - roundedValue) < Number.EPSILON
const numberOfFloorDigits = String(floorValue).length
const numberOfDigits = String(roundedValue).length
if (numberOfFloorDigits > precision) {
return String(floorValue)
} else {
const padding = isInteger ? precision - numberOfFloorDigits : precision - numberOfDigits + 1
if (padding > 0) {
if (isInteger) {
return `${String(floorValue)}.${'0'.repeat(padding)}`
} else {
return `${String(roundedValue)}${'0'.repeat(padding)}`
}
} else {
return String(roundedValue)
}
}
}
function round (precision, number) {
return parseFloat(number.toPrecision(precision))
}
如果您使用 tape 进行测试,那么这里有一些基本测试
import test from 'tape'
import formatNumber from '..path/to/formatNumber.js'
test('formatNumber', (t) => {
t.equal(formatNumber(4, undefined), '', 'undefined number returns an empty string')
t.equal(formatNumber(4, null), '', 'null number return an empty string')
t.equal(formatNumber(4, 0), '0')
t.equal(formatNumber(4, 1.23456789), '1.235')
t.equal(formatNumber(4, 1.23), '1.230')
t.equal(formatNumber(4, 123456789), '123500000')
t.equal(formatNumber(4, 1234567.890123), '1235000')
t.equal(formatNumber(4, 123.4567890123), '123.5')
t.equal(formatNumber(4, 12), '12.00')
t.equal(formatNumber(4, 1.2), '1.200')
t.equal(formatNumber(4, 1.234567890123), '1.235')
t.equal(formatNumber(4, 0.001234567890), '0.001235')
t.equal(formatNumber(5, 123456789), '123460000')
t.end()
})
答案 3 :(得分:1)
使用指数表示法的自动类型转换怎么样?
f = (x, n) => +x.toPrecision(n)
测试:
> f (0.123456789, 6)
0.123457
> f (123456789, 6)
123457000
> f (-123456789, 6)
-123457000
> f (-0.123456789, 6)
-0.123457
> f (-0.123456789, 2)
-0.12
> f (123456789, 2)
120000000
它返回一个数字而不是一个字符串。
答案 4 :(得分:0)
如果要指定小数点后的有效数字,并用T B M K分别替换无关的占位符
// example to 3 sigDigs (significant digits)
//54321 = 54.3M
//12300000 = 12.3M
const moneyFormat = (num, sigDigs) => {
var s = num.toString();
let nn = "";
for (let i = 0; i <= s.length; i++) {
if (s[i] !== undefined) {
if (i < sigDigs) nn += s[i];
else nn += "0";
}
}
nn = nn
.toString()
.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")
.replace(",000,000,000", "B")
.replace(",000,000", "M")
.replace(",000", "k");
if (
nn[nn.length - 4] === "," &&
nn[nn.length - 2] === "0" &&
nn[nn.length - 1] === "0"
) {
let numLetter = "K";
if (parseInt(num) > 999999999999) numLetter = "T";
else if (parseInt(num) > 999999999) numLetter = "B";
else if (parseInt(num) > 999999) numLetter = "M";
console.log("numLetter: " + numLetter);
nn = nn.toString();
let nn2 = ""; // new number 2
for (let i = 0; i < nn.length - 4; i++) {
nn2 += nn[i];
}
nn2 += "." + nn[nn.length - 3] + numLetter;
nn = nn2;
}
return nn;
};