-
-
Save ryasmi/91d7fd30710264affeb9 to your computer and use it in GitHub Desktop.
function convertBase(value, from_base, to_base) { | |
var range = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/'.split(''); | |
var from_range = range.slice(0, from_base); | |
var to_range = range.slice(0, to_base); | |
var dec_value = value.split('').reverse().reduce(function (carry, digit, index) { | |
if (from_range.indexOf(digit) === -1) throw new Error('Invalid digit `'+digit+'` for base '+from_base+'.'); | |
return carry += from_range.indexOf(digit) * (Math.pow(from_base, index)); | |
}, 0); | |
var new_value = ''; | |
while (dec_value > 0) { | |
new_value = to_range[dec_value % to_base] + new_value; | |
dec_value = (dec_value - (dec_value % to_base)) / to_base; | |
} | |
return new_value || '0'; | |
} |
@cyoce there are many ways to represent float numbers, so we don't know which float representation do you want. When we are talking about base, we usually mean integers.
This doesn't work for numbers > 2^53
Any chance adding support for a very big numbers?
THANK YOU! This works great for my converter tool!
conversion has less precision
var x = "89999999179999999"; // String written inside quotes
x=convertBase(x,10,36);
document.getElementById("base36").innerHTML = x;
document.getElementById("base10").innerHTML = convertBase(x,36,10);
/*OUTPUT
base36 : om6c4ucnke8
base10 : 89999999180000000
*/
Here is a bug:
convertBase("04ef57aa335b86bce90cd99144be26fa47645c36624eeb54ae153bc67861f9a7ad96e23e0d200348bd6a442ef96bd04a2c177272bd92fd739f01e0520fa8f0cae9", 16, 36)
returns "5kwmq5si5koww4ww0gcgw48cggsocowosk8c0g84ws8gscowckgs0osssogk4kgc40ggo8w8gko48c0k808wc4os88oc00gs4ow8"
But: convertBase('5kwmq5si5koww4ww0gcgw48cggsocowosk8c0g84ws8gscowckgs0osssogk4kgc40ggo8w8gko48c0k808wc4os88oc00gs4ow8', 36, 16)
returns "4ef57aa335b8700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
Here is some range conditions
let convertBase = (value, from_base, to_base) => {
let range = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/".split("");
if (from_base < 2 || from_base > range.length)
throw new RangeError(`convertBase() from_base argument must be between 2 and ${range.length}`);
if (to_base < 2 || to_base > range.length)
throw new RangeError(`convertBase() to_base argument must be between 2 and ${range.length}`);
let from_range = range.slice(0, from_base);
let to_range = range.slice(0, to_base);
let dec_value = value.split("").reverse().reduce((carry, digit, index) => {
let fromIndex = from_range.indexOf(digit);
if (fromIndex === -1)
throw new Error(`Invalid digit ${digit} for base ${from_base}.`);
return carry + fromIndex * Math.pow(from_base, index);
}, 0);
let new_value = "";
while (dec_value > 0) {
new_value = to_range[dec_value % to_base] + new_value;
dec_value = (dec_value - dec_value % to_base) / to_base;
}
return new_value || "0";
};
Support of large integer using native BigInt, (see browser support)
let bigIntPow = function power(x, y) {// x**y
let ZERO = BigInt(0);
if (y === ZERO) return BigInt(1);
let TWO = BigInt(2);
let p2 = power(x, y / TWO);
if (y % TWO === ZERO) return p2 * p2;
return x * p2 * p2;
};
let convertBaseBigInt = (value, from_base, to_base) => {
let range = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/".split("");
if (from_base < 2 || from_base > range.length)
throw new RangeError(`convertBase() from_base argument must be between 2 and ${range.length}`);
if (to_base < 2 || to_base > range.length)
throw new RangeError(`convertBase() to_base argument must be between 2 and ${range.length}`);
let from_range = range.slice(0, from_base);
let to_range = range.slice(0, to_base);
let from_base_big = BigInt(from_base);
let to_base_big = BigInt(to_base);
let dec_value = value.split("").reverse().reduce((carry, digit, index) => {
let fromIndex = from_range.indexOf(digit);
if (fromIndex === -1)
throw new Error(`Invalid digit ${digit} for base ${from_base}.`);
return carry + BigInt(fromIndex) * bigIntPow(from_base_big, BigInt(index));
}, BigInt(0));
let new_value = "";
while (dec_value > 0) {
new_value = to_range[dec_value % to_base_big] + new_value;
dec_value = (dec_value - dec_value % to_base_big) / to_base_big;
}
return new_value || "0";
};
test
let s = "4ef57aa335b86bce90cd99144be26fa47645c36624eeb54ae153bc67861f9a7ad96e23e0d200348bd6a442ef96bd04a2c";
console.log(convertBaseBigInt(convertBaseBigInt(s, 16, 36), 36, 16) === s);// true
Bug
// Base 10 to Base 26, also get issue Base26 to Base10 with hight numbers ...
// my testcase, nothing to explain ...
{
expected: "DGSJENFCE",
operande: "equal",
data: { num: "897521678123", srcAlphabet: NUMERALS_10.join(""), dstAlphabet: ALPHABET_LATIN.join("") }
},
BUT HAVE "EHTKFOGDF"
"DGSJENFCE" expected because of this
and another website have the same result but with your algo
Note: typeNumAmbiToStr is only for merge number and string to string
function swapBaseRef(valueA: string, baseA: string, ToBaseB: string) {
if (baseA.length !== ToBaseB.length) { throw new RangeError("swapBaseRef: need baseA and ToBaseB lenght equal"); }
return valueA
.split("")
.map((e, i) => { return ToBaseB[baseA.indexOf(e)] })
.join("")
}
export function anyBaseToAnyBase(num: string | number, srcAlphabet: string, dstAlphabet: string) {
let fromBase = srcAlphabet.length,
toBase = dstAlphabet.length;
let from_range = LONGEST_BASE.slice(0, fromBase);
let to_range = LONGEST_BASE.slice(0, toBase).join("");
const number = swapBaseRef(typeNumAmbiToStr(num, srcAlphabet), srcAlphabet, from_range.join(""));
let dec_value = number.split("").reverse().reduce((carry, digit, index) => {
let fromIndex = from_range.indexOf(digit);
if (fromIndex === -1) { throw new Error(`Invalid digit ${digit} for base ${fromBase}.`); }
return carry + fromIndex * Math.pow(fromBase, index);
}, 0);
let new_value = "";
while (dec_value > 0) {
new_value = to_range[dec_value % toBase] + new_value;
dec_value = (dec_value - dec_value % toBase) / toBase;
}
return swapBaseRef(new_value, to_range, dstAlphabet) || dstAlphabet[0];
};
please fixed youre code @ryansmith94 it would be awesome,
it works with small numbers but not with high numbers maybe theyre an issue when divide and float number ...
I saw a package wich have the same issue ("and we go again") ...
Because of this, prefer to use toString() ... ๐
@kzar79 @Juraj-Masiar @crispy-cat @apanasara @joeshae @zakariamouhid @c0ncentus
I moved this code to https://github.com/ryansmith94/baseroo and created issue #1 today and fixed the bug with large numbers. Thanks to @zakariamouhid for the suggested fix, I utilised that and tweaked it to work with TypeScript. Apologies for my slow reply, seemed I had notifications turned off for replies until recently, so thanks to @c0ncentus for persisting with that latest comment which did come through ๐
Now supports floats ryasmi/baseroo#37
It would be great to add support for floats. E.g.
convertBase("1.2", 10, 64)