|
|
1
Community Mohan Dere
6 年前
numberToArray()
:
我已经为您的实现工作了一段时间,并考虑首先分析
numberToArray()
方法首先,我决定创建一个分析十进制数并返回的方法
statistics
关于它,基本上是您从代码的这一部分获得的信息:
if (!int) {
let e = ~~a;
d = a - e;
do {
if (d < 1) ++i;
d *= 10;
} while (!Number.isInteger(d));
}
我使用的方法是下一个(将在内部使用)
numberToArray()
)基本上可以得到下一个信息:
1)
iSection
)十进制数的整数。
2)
小数部分(
dSection
3)
点后的位数(
dDigits
).
点后前导零的数目(
dZeros
).
function getDecimalStats(dec)
{
let dDigits = 0, test = dec, factor = 1, dZeros = 0;
// Store the integer section of the decimal number.
let iSection = ~~dec;
// Get the numbers of digits and zeros after the comma.
while (!Number.isInteger(test))
{
factor = Math.pow(10, ++dDigits);
test = dec * factor;
dZeros += Math.abs(test - (iSection * factor)) < 1 ? 1 : 0;
}
// Store the decimal section as integer.
let dSection = test - (iSection * factor);
// Return an object with all statistics.
return {iSection, dSection, dZeros, dDigits};
};
console.log(getDecimalStats(10.001));
console.log(getDecimalStats(-210.1));
console.log(getDecimalStats(-0.00001));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
当然,如果你不喜欢,你可以把同样的逻辑直接放进去
numberToArray()
correction factor
numberToArray()
方法
function getDecimalStats(dec)
{
let dDigits = 0, test = dec, factor = 1, dZeros = 0;
// Store the integer section of the decimal number.
let iSection = ~~dec;
// Get the numbers of digits and zeros after the comma.
while (!Number.isInteger(test))
{
factor = Math.pow(10, ++dDigits);
test = dec * factor;
dZeros += Math.abs(test - (iSection * factor)) < 1 ? 1 : 0;
}
// Store the decimal section as integer.
let dSection = test - (iSection * factor);
// Return an object with all statistics.
return {iSection, dSection, dZeros, dDigits};
};
function numberToArray(n)
{
let r = [];
if (Math.abs(n) == 0)
return [n];
let [a, int = Number.isInteger(a), g = []] = [n || this.valueOf()];
// Get the stats of the decimal number.
let {dSection, dZeros} = getDecimalStats(a);
// Push the integer part on the array.
for (; ~~a; r.unshift(~~(a % 10)), a /= 10);
// Push the decimal part on the array.
if (!int)
{
// Push decimal digits on temporal array "g".
for (; ~~dSection; g.unshift(~~(dSection % 10)), dSection /= 10);
// Define the correction factor for the next operation.
let cf = 10 ** (++dZeros);
// Map g[0] to a decimal number and push elements on the array.
g[0] = (g[0] * cf) * ((10 ** -dZeros) * cf) / (cf * cf);
r.push(...g);
}
return r;
}
let tests = [
0, 200, 100.00015, -123, 4.4, 44.44, -0.01, 123,
2.718281828459, 321.7000000001, 809.56,
1.61803398874989, 1.999, 100.01, 545454.45,
-7, -83.782, 12, 1.50, 100.0001
];
let arrays = tests.map(n => [...numberToArray(n)]);
console.log({tests, arrays});
.as控制台{背景颜色:黑色!重要;颜色:石灰;}
方法
arrayToNumber()
对于这一个,我决定自己去(实际上忽略了你当前的逻辑)。下一种方法将使用前面提到的方法
getDecimalStats()
主要是
Array::reduce()
function getDecimalStats(dec)
{
let dDigits = 0, test = dec, factor = 1, dZeros = 0;
// Store the integer section of the decimal number.
let iSection = ~~dec;
// Get the numbers of digits and zeros after the comma.
while (!Number.isInteger(test))
{
factor = Math.pow(10, ++dDigits);
test = dec * factor;
dZeros += Math.abs(test - (iSection * factor)) < 1 ? 1 : 0;
}
// Store the decimal section as integer.
let dSection = test - (iSection * factor);
// Return an object with all statistics.
return {iSection, dSection, dZeros, dDigits};
};
function arrayToNumber(a)
{
// Get the index of the first decimal number.
let firstDecIdx = a.findIndex(
x => Math.abs(x) > 0 && Math.abs(x) < 1
);
// Get stats about the previous decimal number.
let {dZeros} = getDecimalStats(firstDecIdx >= 0 ? a[firstDecIdx] : 0);
// Normalize firstDecIdx.
firstDecIdx = firstDecIdx < 0 ? a.length : firstDecIdx;
// Reduce the array to get the number.
let number = a.reduce(
({num, dIdx, dPow}, n, i) =>
{
// Define the correction factor.
let cf = 10 ** (dPow + i - dIdx);
if (i < dIdx)
num += n * (10 ** (dIdx - i - 1));
else if (i === dIdx)
num = ((num * cf) + (n * cf)) / cf;
else
num = ((num * cf) + n) / cf;
return {num, dIdx, dPow};
},
{num: 0, dIdx: firstDecIdx, dPow: ++dZeros}
);
return number.num;
}
let tests = [
[0],
[2, 0, 0],
[1, 0, 0, 0.0001, 5],
[-1, -2, -3],
[4, 0.4],
[4, 4, 0.4, 4],
[-0.01],
[1, 2, 3],
[2, 0.7, 1, 8, 2, 8, 1, 8, 2, 8, 4, 5, 9],
[3, 2, 1, 0.7, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[8, 0, 9, 0.5, 6],
[1, 0.6, 1, 8, 0, 3, 3, 9, 8, 8, 7, 4, 9, 8, 9],
[1, 0.9, 9, 9],
[1, 0, 0, 0.01],
[5, 4, 5, 4, 5, 4, 0.4, 5, 0],
[-7],
[-8,-3, -0.7, -8, -2],
[1, 2],
[1, 0.5],
[1, 0, 0, 0.0001]
];
let numbers = tests.map(n => arrayToNumber(n));
console.log(numbers);
.as控制台{背景颜色:黑色!重要;颜色:石灰;}
.作为控制台包装{最大高度:100%!重要;顶部:0;}
最后,我希望您能重视我的努力,显然我的解决方案可以有很多改进(因此,欢迎任何建议)。例如,目前没有或很少进行安全检查。
|