我在python中有一个工作脚本,使用long(16)
基于指定的基数进行字符串到整数的转换:
modulus=public_key["n"]
modulusDecoded = long(public_key["n"], 16)
打印:
8079d7ae567dd2c02dadd1068843136314fa3893fa1fb1ab331682c6a85cad62b208d66c9974bbbb15d52676fd9907efb158c284e96f5c7a4914fd927b7326c40efa14922c68402d05ff53b0e4ccda90bbee5e6c473613e836e2c79da1072e366d0d50933327e77651b6984ddbac1fdecf1fd8fa17e0f0646af662a8065bd873
和
90218878289834622370514047239437874345637539049004160177768047103383444023879266805615186962965710608753937825108429415800005684101842952518531920633990402573136677611127418094912644368840442620417414685225340199872975797295511475162170060618806831021437109054760851445152320452665575790602072479287289305203
分别。
这看起来像十六进制到十进制转换。
我尝试在JS中获得相同的结果,但parseInt()
和parseFloat()
产生了完全不同的东西。最重要的是,JavaScript似乎不喜欢输入字符串中的字符,有时会返回NaN。
有人可以提供一个函数/指导如何获得与Python脚本相同的功能吗?
答案 0 :(得分:6)
JavaScript中的数字是浮点数,因此在某个数字后它们总是会失去精度。要拥有无限数字,我们可以使用0到9之间的数字数组,它具有无限范围。要基于十六进制字符串输入执行此操作,我执行十六进制到int数组转换,然后使用double dabble algorithm将数组转换为BCD。这可以很容易打印出来:
const hexToArray = arr => arr.split("").map(n => parseInt(n,16));
const doubleDabble = arr => {
var l = arr.length;
for( var b = l * 4; b--;){
//add && leftshift
const overflow = arr.reduceRight((carry,n,i) => {
//apply the >4 +3, then leftshift
var shifted = ((i < (arr.length - l ) && n>4)?n+3:n ) << 1;
//just take the right four bits and add the eventual carry value
arr[i] = (shifted & 0b1111) | carry;
//carry on
return shifted > 0b1111;
}, 0);
// we've exceeded the current array, lets extend it:
if(overflow) arr.unshift(overflow);
}
return arr.slice(0,-l);
};
const arr = hexToArray("8079d7");
const result = doubleDabble(arr);
console.log(result.join(""));
答案 1 :(得分:3)
使用内置的api parseInt
,您可以在Firefox上获得高达100的精确度,在Chrome上获得20位精确度。
a = parseInt('8079d7ae567dd2c02dadd1068843136314fa3893fa1fb1ab331682c6a85cad62b208d66c9974bbbb15d52676fd9907efb158c284e96f5c7a4914fd927b7326c40efa14922c68402d05ff53b0e4ccda90bbee5e6c473613e836e2c79da1072e366d0d50933327e77651b6984ddbac1fdecf1fd8fa17e0f0646af662a8065bd873', 16)
a.toPrecision(110)
> Uncaught RangeError: toPrecision() argument must be between 1 and 21
# Chrome
a.toPrecision(20)
"9.0218878289834615508e+307"
# Firefox
a.toPrecision(100)
"9.021887828983461550807409292694387726882781812072572899692574101215517323445643340153182035092932819e+307"
- 让p成为? ToInteger(精度)。
......- 如果p < 1或p> 100,抛出RangeError异常。
醇>
答案 2 :(得分:0)
如this answer所述,JavaScript数字不能代表大于9.007199254740991e+15的整数而不会损失精度。
在JavaScript中使用较大的整数需要BigInt库或其他专用代码,然后大整数通常表示为字符串或数组。
重用this answer中的代码有助于转换十六进制数字表示
8079d7ae567dd2c02dadd1068843136314fa3893fa1fb1ab331682c6a85cad62b208d66c9974bbbb15d52676fd9907efb158c284e96f5c7a4914fd927b7326c40efa14922c68402d05ff53b0e4ccda90bbee5e6c473613e836e2c79da1072e366d0d50933327e77651b6984ddbac1fdecf1fd8fa17e0f0646af662a8065bd873
到十进制表示
90218878289834622370514047239437874345637539049004160177768047103383444023879266805615186962965710608753937825108429415800005684101842952518531920633990402573136677611127418094912644368840442620417414685225340199872975797295511475162170060618806831021437109054760851445152320452665575790602072479287289305203
如以下代码段所示:
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 =
'8079d7ae567dd2c02dadd1068843136314fa389'+
'3fa1fb1ab331682c6a85cad62b208d66c9974bb'+
'bb15d52676fd9907efb158c284e96f5c7a4914f'+
'd927b7326c40efa14922c68402d05ff53b0e4cc'+
'da90bbee5e6c473613e836e2c79da1072e366d0'+
'd50933327e77651b6984ddbac1fdecf1fd8fa17'+
'e0f0646af662a8065bd873';
//convert largeNumber from base 16 to base 10
var largeIntDecimal = convertBase(largeNumber, 16, 10);
//show decimal result in console:
console.log(largeIntDecimal);
//check that it matches the expected output:
console.log('Matches expected:',
largeIntDecimal === '90218878289834622370514047239437874345637539049'+
'0041601777680471033834440238792668056151869629657106087539378251084294158000056'+
'8410184295251853192063399040257313667761112741809491264436884044262041741468522'+
'5340199872975797295511475162170060618806831021437109054760851445152320452665575'+
'790602072479287289305203'
);
//check that conversion and back-conversion results in the original number
console.log('Converts back:',
convertBase(convertBase(largeNumber, 16, 10), 10, 16) === largeNumber
);