- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
要求:
将输入的整数或小数转换为数组,并将可能包含小数的整数数组转换为数字。
限制:
在此过程中不要使用字符串方法或将输入或输出转换为字符串(在编写的每个版本的代码中都有一个 self 强加的限制)。
背景和用例
BigInt
在某些浏览器中可用,但不是 BigDecimal
。使用 JavaScript 编程语言应该可以实现从整数或小数到数组以及数组到整数或小数的转换。输入和输出在过程中不需要转换为字符串。
能够通过调整数组的nth 索引处的小数或整数来调整整数或小数的nth 位,以尝试解决OEIS A217626直接,例如
~~(128.625*9*1.074)//1243
~~(128.625*9*1.144)//1324
可以通过引用数组的索引来操作小数部分,然后将数组转换回数字。
当前的规范是 WIP,描述与输入的小数部分处理相关的内容可能被认为具有挑战性,特别是在有前导零的地方。
Input <----------> Output
-123 [-1,-2,-3]
4.4 [4,0.4]
44.44 [4,4,0.4,4]
-0.01 [-0.01]
123 [1,2,3]
200 [2,0,0]
2.718281828459 [2,0.7,1,8,2,8,1,8,2,8,4,5,8,9]
321.7000000001 [3,2,1,0.7,0,0,0,0,0,0,0,0,1]
809.56 [8,0,9,0.5,6]
1.61803398874989 [1,0.6,1,8,0,3,3,9,8,8,7,4,9,8,9]
1.999 [1,0.9,9,9]
100.01 [1,0,0,0.01]
545454.45 [5,4,5,4,5,4,0.4,5]
-7 [-7]
-83.782 [-8,-3,-0.7,-8,-2]
1.5 [1,0.5]
100.0001 [1,0,0,0.0001]
本质上,我试图将一个整数或小数展开到一个数组中。将数字或整数转换为数组的函数必须能够转换为生成器函数,才能实现
[...Math.E] -> [2, 0.7, 1, 8, 2, 8, 1, 8, 2, 8, 4, 5, 9] -> 2.718281828459
通过将函数设置为 Number.prototype[Symbol.iterator]
的值到 numberToArray
。
最新版本的代码(一些概念和代码的原始版本基于 Get decimal portion of a number with JavaScript ; Converting int value to String without using toString and parseInt method ; Convert integer to array of digits 处的问题和答案),在测试结果输出中有两个错误来自 arrayToNumber
100.05010000000497
的案例应该是 100.00015
而 -83.082
应该是 -83.782
。
function numberToArray(n) {
if (Math.abs(n) == 0 || Math.abs(n) == -0) {
return [n]
}
const r = [];
let [
a, int = Number.isInteger(a), d = g = [], e = i = 0
] = [ n || this.valueOf()];
if (!int) {
let e = ~~a;
d = a - e;
do {
if (d < 1) ++i;
d *= 10;
} while (!Number.isInteger(d));
}
for (; ~~a; r.unshift(~~(a % 10)), a /= 10);
if (!int) {
for (; ~~d; g.unshift(~~(d % 10)), d /= 10);
g[0] = g[0] * (1 * (10 ** -i))
r.push(...g);
}
return r;
}
function arrayToNumber(a) {
if ((Math.abs(a[0]) == 0 || Math.abs(a[0]) == -0)
&& a.length == 1) return a[0];
const [
g, r = x => x.length == 1
? x[0]
: x.length === 0
? x
: x.reduce((a, b) => a + b)
, b = a.find(x => g(x)), p = a.findIndex(x => g(x))
] = [x => !Number.isInteger(x)];
let [i, j] = [b ? p : a.length, -1];
return a.length === 1
? a[0]
: b && p
? r(a.slice(0, p).map(x => i ? x * (10 ** --i) : x))
+ (a[p] + (a[p + 1] !== undefined
? r(a.slice(p + 1).map(x => x * (10 ** --j)))
: 0))
: r(a.map(x => i ? x * (10 ** --i) : x))
}
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)]);
let numbers = arrays.map(n => arrayToNumber(n));
console.log({tests, arrays, numbers});
问题:
最佳答案
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
)。
4) 点后的前导零数 (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()
方法中。因此,在完成之前的功能之后,我对您的代码进行了一些重组,并添加了一些注释以帮助我了解您在做什么。最后,在修改你的代码后,我发现错误的数组映射主要是因为使用 float 运算时的算术精度。在对这个问题进行了一段时间的调查之后,我找到了一个基于数学校正因子
的解决方案(它在应用时在代码中进行了注释)。总而言之,到现在为止,我已经有了 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-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
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-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
最后,我希望你能重视我的努力,显然我的解决方案可以有很多改进(因此,欢迎任何建议)。例如,目前没有或很少进行安全检查。
关于javascript - 数字(整数或小数)到数组,数组到数字(整数或小数)而不使用字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54433007/
如何使用 SPListCollection.Add(String, String, String, String, Int32, String, SPListTemplate.QuickLaunchO
我刚刚开始使用 C++ 并且对 C# 有一些经验,所以我有一些一般的编程经验。然而,似乎我马上就被击落了。我试过在谷歌上寻找,以免浪费任何人的时间,但没有结果。 int main(int argc,
这个问题已经有答案了: In Java 8 how do I transform a Map to another Map using a lambda? (8 个回答) Convert a Map>
我正在使用 node + typescript 和集成的 swagger 进行 API 调用。我 Swagger 提出以下要求 http://localhost:3033/employees/sear
我是 C++ 容器模板的新手。我收集了一些记录。每条记录都有一个唯一的名称,以及一个字段/值对列表。将按名称访问记录。字段/值对的顺序很重要。因此我设计如下: typedef string
我需要这两种方法,但j2me没有,我找到了一个replaceall();但这是 replaceall(string,string,string); 第二个方法是SringBuffer但在j2me中它没
If string is an alias of String in the .net framework为什么会发生这种情况,我应该如何解释它: type JustAString = string
我有两个列表(或字符串):一个大,另一个小。 我想检查较大的(A)是否包含小的(B)。 我的期望如下: 案例 1. B 是 A 的子集 A = [1,2,3] B = [1,2] contains(A
我有一个似乎无法解决的小问题。 这里...我有一个像这样创建的输入... var input = $(''); 如果我这样做......一切都很好 $(this).append(input); 如果我
我有以下代码片段 string[] lines = objects.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.No
这可能真的很简单,但我已经坚持了一段时间了。 我正在尝试输出一个字符串,然后输出一个带有两位小数的 double ,后跟另一个字符串,这是我的代码。 System.out.printf("成本:%.2
以下是 Cloud Firestore 列表查询中的示例之一 citiesRef.where("state", ">=", "CA").where("state", "= 字符串,我们在Stack O
我正在尝试检查一个字符串是否包含在另一个字符串中。后面的代码非常简单。我怎样才能在 jquery 中做到这一点? function deleteRow(locName, locID) { if
这个问题在这里已经有了答案: How to implement big int in C++ (14 个答案) 关闭 9 年前。 我有 2 个字符串,都只包含数字。这些数字大于 uint64_t 的
我有一个带有自定义转换器的 Dozer 映射: com.xyz.Customer com.xyz.CustomerDAO customerName
这个问题在这里已经有了答案: How do I compare strings in Java? (23 个回答) 关闭 6 年前。 我想了解字符串池的工作原理以及一个字符串等于另一个字符串的规则是
我已阅读 this问题和其他一些问题。但它们与我的问题有些无关 对于 UILabel 如果你不指定 ? 或 ! 你会得到这样的错误: @IBOutlet property has non-option
这两种方法中哪一种在理论上更快,为什么? (指向字符串的指针必须是常量。) destination[count] 和 *destination++ 之间的确切区别是什么? destination[co
This question already has answers here: Closed 11 years ago. Possible Duplicates: Is String.Format a
我有一个Stream一个文件的,现在我想将相同的单词组合成 Map这很重要,这个词在 Stream 中出现的频率. 我知道我必须使用 collect(Collectors.groupingBy(..)
我是一名优秀的程序员,十分优秀!