用小数格式化数字
Posted
技术标签:
【中文标题】用小数格式化数字【英文标题】:Formatting a number by a decimal 【发布时间】:2019-05-07 06:48:20 【问题描述】:我正在尝试转换一个数字数组,使每个数字只有一个非零数字。 所以基本上
"7970521.5544"
给我
["7000000", "900000", "70000", "500", "20", "1", ".5", ".05", ".004", ".0004"]
我试过了:
var j = "7970521.5544"
var k =j.replace('.','')
var result = k.split('')
for (var i = 0; i < result.length; i++)
console.log(parseFloat(Math.round(result[i] * 10000) /10).toFixed(10))
任何想法,我不知道从哪里开始?
【问题讨论】:
当您执行replace('.','')
时,您将失去小数位的位置。我建议先使用split('.')
,然后分别处理整数和小数部分
【参考方案1】:
算法:
Split 使用十进制表示法分成两部分的数字。 运行 for 循环以将每个数字乘以10
的相应幂,例如:
value = value * Math.pow(10, index); // for digits before decimal
value = value * Math.pow(10, -1 * index); // for digits after decimal
然后,filter 非零元素和concatenate 两个数组。 (记得重新reverse左边的数组)
var n = "7970521.5544"
var arr = n.split('.'); // '7970521' and '5544'
var left = arr[0].split('').reverse(); // '1250797'
var right = arr[1].split(''); // '5544'
for(let i = 0; i < left.length; i++)
left[i] = (+left[i] * Math.pow(10, i) || '').toString();
for(let i = 0; i < right.length; i++)
right[i] = '.' + +right[i] * Math.pow(10, -i);
let res = left.reverse() // reverses the array
.filter(n => !!n)
// ^^^^^^ filters those value which are non zero
.concat(right.filter(n => n !== '.0'));
// ^^^^^^ concatenation
console.log(res);
【讨论】:
这包括“0”,以及十进制中的前导“0”,两者都不同于 OP 所需的结果。输出也是小数点后一位:5
而不是 .5
。【参考方案2】:
您可以使用padStart
和padEnd
结合reduce()
来构建数组。您要填充的数量将是小数点的索引减去小数点左侧和右侧相反项的循环中的索引。
使用reduce()
,您可以使用填充字符串创建一个新数组,注意避免零和小数本身。
let s = "7970521.5544"
let arr = s.split('')
let d_index = s.indexOf('.')
if (d_index == -1) d_index = s.length // edge case for nums with no decimal
let nums = arr.reduce((arr, n, i) =>
if (n == 0 || i == d_index) return arr
arr.push((i < d_index)
? n.padEnd(d_index - i, '0')
: '.' + n.padStart(i - d_index, '0'))
return arr
, [])
console.log(nums)
【讨论】:
【参考方案3】:你可以split
你的字符串然后使用Array.prototype.reduce
方法。记下小数位,然后相应地用"0"
填充您的值。如下所示:
var s = "7970521.5544";
var original = s.split('');
var decimalPosition = original.indexOf('.');
var placeValues = original.reduce((accum, el, idx) =>
var f = el;
if (idx < decimalPosition)
for (let i = idx; i < (decimalPosition - 1); i++)
f += "0";
accum.push(f);
else if (idx > decimalPosition)
let offset = Math.abs(decimalPosition - idx) - 2;
for (let i = 0; i <= offset; i++)
f = "0" + f;
f = "." + f;
accum.push(f);
return accum;
, []);
console.log(placeValues);
【讨论】:
【参考方案4】:较短的替代方案(在 IE 中不起作用):
var s = "7970521.5544"
var i = s.split('.')[0].length
var a = [...s].reduce((a, c) => (i && +c && a.push(i > 0 ?
c.padEnd(i, 0) : '.'.padEnd(-i, 0) + c), --i, a), [])
console.log( a )
IE版本:
var s = "7970521.5544"
var i = s.split('.')[0].length
var a = [].reduce.call(s, function(a, c) return (i && +c && a.push(i > 0 ?
c + Array(i).join(0) : '.' + Array(-i).join(0) + c), --i, a); , [])
console.log( a )
【讨论】:
【参考方案5】:function standardToExpanded(n)
return String(String(Number(n))
.split(".")
.map(function(n, i)
// digits, decimals..
var v = n.split("");
// reverse decimals..
v = i ? v.reverse() : v;
v = v
.map(function(x, j)
// expanded term..
return Number([x, n.slice(j + 1).replace(/\d/g, 0)].join(""));
)
.filter(Boolean); // omit zero terms
// unreverse decimals..
v = i ? v.map(function(x)
return '.' + String(x).split('').reverse().join('')
).reverse() : v;
return v;
)).split(',');
console.log(standardToExpanded("7970521.5544"));
// -> ["7000000", "900000", "70000", "500", "20", "1", ".5", ".05", ".004", ".0004"]
这看起来像是我儿子旧的三年级(核心课程)数学书里的东西!
【讨论】:
以上是关于用小数格式化数字的主要内容,如果未能解决你的问题,请参考以下文章