在JavaScript中,我有一个非常大的数字表示为二进制:
var largeNumber = '11010011010110100001010011111010010111011111000010010111000111110011111011111000001100000110000011000001100111010100111010101110100010001011010101110011110000011000001100000110000011001001100000110000011000001100000110000111000011100000110000011000001100000110000011000010101100011001110101101001100110100100000110000011000001100000110001001101011110110010001011010001101011010100011001001110001110010100111011011111010000110001110010101010001111010010000101100001000001100001011000011011111000011110001110111110011111111000100011110110101000101100000110000011000001100000110000011010011101010110101101001111101001010010111101011000011101100110010011001001111101'当我使用parseInt(largeNumber, 10)l将它转换为十进制时,它给了我1.5798770299367407e+199,但是当我试图将它转换回二进制时:
parseInt(`1.5798770299367407e+199`, 2)它返回1 (我认为这与parseInt通过舍入值的工作方式有关),当我期望看到最初的largeNumber二进制表示时。你能解释一下我的这种行为吗?以及如何在JavaScript中将其转换回原始状态?
编辑:这个问题是我实验的结果,当时我正在尝试存储和传输大量的布尔数据。largeNumber是布尔值集合[true,true,false,true ...]的表示,必须在客户端、客户端工作者和服务器之间共享。
发布于 2016-09-05 16:33:39
当您将其转换回二进制时,您不会将其解析为基2,这是错误的。您还试图将整数解析为浮点数,这可能会导致不精确。用这一行:
parseInt(`1.5798770299367407e+199`, 2)您是在告诉JS将基数10解析为基2!您需要做的是将其转换为类似于这样的二进制(注意parseFloat的使用):
var largeNumber = '11010011010110100001010011111010010111011111000010010111000111110011111011111000001100000110000011000001100111010100111010101110100010001011010101110011110000011000001100000110000011001001100000110000011000001100000110000111000011100000110000011000001100000110000011000010101100011001110101101001100110100100000110000011000001100000110001001101011110110010001011010001101011010100011001001110001110010100111011011111010000110001110010101010001111010010000101100001000001100001011000011011111000011110001110111110011111111000100011110110101000101100000110000011000001100000110000011010011101010110101101001111101001010010111101011000011101100110010011001001111101';
//intLN is integer of large number
var intLN = parseFloat(largeNumber, 2); //here, you used base 10 to parse as integer, Incorrect
console.log(intLN);
var largeNumberConvert = intLN.toString(2); //here, we convert back to binary with toString(radix).
console.log(largeNumberConvert);
在此之前,您将十进制转换为二进制。您需要做的是调用toString(radix)将其转换回二进制文件,因此:
var binaryRepresentation = integerFormOfLargeNumber.toString(2);如果您查看输出,您会看到:
Infinity
Infinity因为你的二进制数很大,它会影响结果。因为JS最多支持64位,所以这个数字太大了。它会引起Infinity,而且不精确。如果您尝试将largeNumberConvert从二进制转换为十进制,如下所示:
parseInt(largeNumberConvert, 10);您可以看到它输出Infinity。
发布于 2016-09-05 21:42:03
正如在Andrew L.'s answer中所指出的,以及一些评论者所指出的,您的largeNumber超过了JavaScript可以表示为一个普通数字的整数,而不会丢失精度--即9.007199254740991e+15。
如果您想使用较大的整数,您将需要一个BigInt库或其他特殊用途的代码。
下面是一些代码,演示如何在不同的基表示之间转换任意大的正整数,显示largeNumber的精确十进制表示形式是
15 798 770 299 367 407 299 367 407 025 345 297 491 683 306 908 462 684 165 669 735 033 278 996 876 231 474 309 788 453 071 122 111 686 268 816 862 247 538 905 966 252 886 438 931 450 432 740 141 331 094 589 505 960 171 298 398 197 475 197 475 262 433 234 991 526 525
function parseBigInt(bigint, base) {
//convert bigint string to array of digit values
for (var values = [], i = 0; i < bigint.length; i++) {
values[i] = parseInt(bigint.charAt(i), base);
}
return values;
}
function formatBigInt(values, base) {
//convert array of digit values to bigint string
for (var bigint = '', i = 0; i < values.length; i++) {
bigint += values[i].toString(base);
}
return bigint;
}
function convertBase(bigint, inputBase, outputBase) {
//takes a bigint string and converts to different base
var inputValues = parseBigInt(bigint, inputBase),
outputValues = [], //output array, little-endian/lsd order
remainder,
len = inputValues.length,
pos = 0,
i;
while (pos < len) { //while digits left in input array
remainder = 0; //set remainder to 0
for (i = pos; i < len; i++) {
//long integer division of input values divided by output base
//remainder is added to output array
remainder = inputValues[i] + remainder * inputBase;
inputValues[i] = Math.floor(remainder / outputBase);
remainder -= inputValues[i] * outputBase;
if (inputValues[i] == 0 && i == pos) {
pos++;
}
}
outputValues.push(remainder);
}
outputValues.reverse(); //transform to big-endian/msd order
return formatBigInt(outputValues, outputBase);
}
var largeNumber =
'1101001101011010000101001111101001011101' +
'1111000010010111000111110011111011111000' +
'0011000001100000110000011001110101001110' +
'1010111010001000101101010111001111000001' +
'1000001100000110000011001001100000110000' +
'0110000011000001100001110000111000001100' +
'0001100000110000011000001100001010110001' +
'1001110101101001100110100100000110000011' +
'0000011000001100010011010111101100100010' +
'1101000110101101010001100100111000111001' +
'0100111011011111010000110001110010101010' +
'0011110100100001011000010000011000010110' +
'0001101111100001111000111011111001111111' +
'1000100011110110101000101100000110000011' +
'0000011000001100000110100111010101101011' +
'0100111110100101001011110101100001110110' +
'0110010011001001111101';
//convert largeNumber from base 2 to base 10
var largeIntDecimal = convertBase(largeNumber, 2, 10);
function groupDigits(bigint){//3-digit grouping
return bigint.replace(/(\d)(?=(\d{3})+$)/g, "$1 ");
}
//show decimal result in console:
console.log(groupDigits(largeIntDecimal));
//converting back to base 2:
var restoredOriginal = convertBase(largeIntDecimal, 10, 2);
//check that it matches the original:
console.log(restoredOriginal === largeNumber);
发布于 2020-03-04 09:32:05
如果您希望传输大量二进制数据,则应该使用BigInt。BigInt允许您表示任意数量的位。
// parse large number from string
let numString = '1101001101011010000101001111101001011101111100001001'
// as number
let num = BigInt('0b' + numString)
// now num holds large number equivalent to numString
console.log(num) // 3718141639515913n
// print as base 2
console.log(num.toString(2)) // 1101001101011010000101001111101001011101111100001001帮助函数
// some helper functions
// get kth bit from right
function getKthBit(x, k){
return (x & (1n << k)) >> k;
}
// set kth bit from right to 1
function setKthBit(x, k){
return (1n << k) | x;
}
// set kth bit from right to 0
function unsetKthBit(x, k){
return (x & ~(1n << k));
}
getKthBit(num, 0n);
// 1n
getKthBit(num, 5n);
// 0n
setKthBit(num, 1n).toString(2);
// 1101001101011010000101001111101001011101111100001011
setKthBit(num, 4n);
// 1101001101011010000101001111101001011101111100011001
unsetKthBit(num, 0n).toString(2);
// 1101001101011010000101001111101001011101111100001000
unsetKthBit(num, 0n).toString(2);
// 1101001101011010000101001111101001011101111100000001为了方便起见,如果要序列化回客户机,您可能需要将其添加到BigInt中。然后你可以把它读回一个字符串。否则,您将得到"Uncaught :不知道如何序列化BigInt“,因为出于某种原因,Javascript对象符号不知道如何序列化Javascript中的一种类型。
Object.defineProperty(BigInt.prototype, "toJSON", {
get() {
"use strict";
return () => this.toString() + 'n';
}
});https://stackoverflow.com/questions/39334494
复制相似问题