118

I would like to convert numbers between different bases, such as hexadecimal and decimal.

Example: How do you convert hexadecimal 8F to decimal?

Yves
  • 12,059
  • 15
  • 53
  • 57
  • I have seen precisely ZERO answers to the question. If I am reading this correctly, the demand was for converting *NUMBERS* between bases. However fancy, hacky, deferring and in some cases completely Big-O oblivious, all the answers go along the "for instance" path of adjusting the problem to the solution you can throw together. Not one of those actually returns a number. Some at least return an array of digits, which is not too bad, but strings are not numbers and chaining `parseInt` with `toString` is lousy performance. I'll come back and post an imperfect solution that deals with numbers. – Ricardo Sep 06 '22 at 12:12

21 Answers21

154

The API

To convert to a number from a hex string:

parseInt(string, radix)
  • string: Required. The string to be parsed

  • radix: Optional. A number (from 2 to 36) that represents the numeral system to be used

To convert from a number to a hex string:

NumberObject.toString(radix)
  • radix: Optional. Specifies the base radix you would like the number displayed as.

Example radix values:

  • 2 - The number will show as a binary value
  • 8 - The number will show as an octal value
  • 16 - The number will show as an hexadecimal value

Example Usage

Integer value to hex:

var i = 10;
console.log( i.toString(16) );

Hex string to integer value:

var h = "a";
console.log( parseInt(h, 16) );

Integer value to decimal:

 var d = 16;
 console.log( d.toString(10) );
Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
aehlke
  • 15,225
  • 5
  • 36
  • 45
  • this is even better. reverse. – Yves Aug 26 '09 at 20:55
  • I'm not seeing how the first converts to hexadecimal. Can you explain it please? In addition, the second will result in hexadecimal and not decimal as labelled. – Russ Cam Aug 26 '09 at 21:53
  • @Russ Cam: The first takes the base as a parameter - hexadecimal is base 16 - and returns a string of that number's representation in that base. You're incorrect about the second - it does indeed result in a decimal value. – aehlke Aug 26 '09 at 22:25
  • @Wahnfrieden - I misinterpreted what you'd put. It's clear to me now :) – Russ Cam Aug 26 '09 at 23:06
  • I think your answer only focus on this example "How to convert hexadecimal 8F to decimal?".It does not cover this question "How do you convert numbers between different bases in JavaScript?" – Alex Nguyen Feb 12 '15 at 09:49
  • 8
    This fails for bases greater than 36, because `toString` throws a `RangeError`. Large bases clearly don't make sense to represent as characters. – Anko - inactive in protest Jun 27 '16 at 00:49
  • @PeterKrauss: parseInt("6f1", 32) === 6625 for me. Where do you see this? Check for typos? – jmrk Feb 02 '19 at 21:33
  • Hi @jmrk thanks (!), there was a version problem, so I deleted the comment with **bolds** to not confuse readers... The only NOTICES: 1) take care with old versions of browsers or NodeJS; 2) there are no `BigInt.parseInt()` at this moment, it will be replaced by [`BigInt.fromstring()` and `Number. fromstring()`](https://github.com/tc39/proposal-number-fromstring). – Peter Krauss Feb 03 '19 at 09:46
  • Convient form to convert a number from one base to another: `parseInt("abc", 33).toString(16)` – Valentin Safonnikov Jul 29 '21 at 11:17
35

Update 2023-01-05: Now supports large numbers and floats via https://github.com/ryasmi/baseroo

I came to this post needing to convert from base 10 to 62 and vice-versa. Whilst the solutions here are great, parseInt and toString only support base 2 to 36. So if anyone finds themselves in a similar position to me needing base 2 to 62, I've pasted my solution below.

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';
}
Ryan Smith
  • 1,255
  • 2
  • 13
  • 16
26

You may try the following code, which also supports arbitrary precision numbers (larger than 2^53).

function convertBase(str, fromBase, toBase) {

    const DIGITS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/";

    const add = (x, y, base) => {
        let z = [];
        const n = Math.max(x.length, y.length);
        let carry = 0;
        let i = 0;
        while (i < n || carry) {
            const xi = i < x.length ? x[i] : 0;
            const yi = i < y.length ? y[i] : 0;
            const zi = carry + xi + yi;
            z.push(zi % base);
            carry = Math.floor(zi / base);
            i++;
        }
        return z;
    }

    const multiplyByNumber = (num, x, base) => {
        if (num < 0) return null;
        if (num == 0) return [];

        let result = [];
        let power = x;
        while (true) {
            num & 1 && (result = add(result, power, base));
            num = num >> 1;
            if (num === 0) break;
            power = add(power, power, base);
        }

        return result;
    }

    const parseToDigitsArray = (str, base) => {
        const digits = str.split('');
        let arr = [];
        for (let i = digits.length - 1; i >= 0; i--) {
            const n = DIGITS.indexOf(digits[i])
            if (n == -1) return null;
            arr.push(n);
        }
        return arr;
    }

    const digits = parseToDigitsArray(str, fromBase);
    if (digits === null) return null;

    let outArray = [];
    let power = [1];
    for (let i = 0; i < digits.length; i++) {
        digits[i] && (outArray = add(outArray, multiplyByNumber(digits[i], power, toBase), toBase));
        power = multiplyByNumber(fromBase, power, toBase);
    }

    let out = '';
    for (let i = outArray.length - 1; i >= 0; i--)
        out += DIGITS[outArray[i]];

    return out;
}

Usage:

console.log(convertBase("5a2a9c826c75045be9ba8fbffc80c6f25a2a9c826c75045be9ba8fbffc80c6f2",16,64));
// Returns: 5EGD89ItghrWrGfL/O0NL9qaFO2r7k4m+CWzX/YwcrO

console.log(convertBase("5EGD89ItghrWrGfL/O0NL9qaFO2r7k4m+CWzX/YwcrO",64,16));
// Returns: 5a2a9c826c75045be9ba8fbffc80c6f25a2a9c826c75045be9ba8fbffc80c6f2

The basic code has been found here, I have a bit improved it to also support up to base 64.

Zamicol
  • 4,626
  • 1
  • 37
  • 42
Slavik Meltser
  • 9,712
  • 3
  • 47
  • 48
16

The following diagram might help. Note that to convert from base 16 to base 2 you need to convert first to base 10 and then base 2.

Base conversion

Maria Ines Parnisari
  • 16,584
  • 9
  • 85
  • 130
  • Hola Inés! I could not agree to your proposal here. It's not like it's incorrect, but when you're converting between bases where one of them is a power of the other (16 = 2^4), the conversion can easily be done directly. In this case, each hexadecimal digit corresponds to 4 binary digits. Also, `parseInt` is totally cheating. – Ricardo Sep 23 '22 at 06:53
13

This function generate decimal number to any base from 2 to 36.(as like javascript)

But you can Increase the base more than 36 just by adding new character in keys[] like lowercase["a","b"]

function toBase(num, radix = 10) { // only i64 numbers
  var keys = ['', '', 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
  if (!(radix >= 2 && radix <= keys.length)) throw new RangeError("toBase() radix argument must be between 2 and " + keys.length)

  if (num < 0) var isNegative = true
  if (isNaN(num = Math.abs(+num))) return NaN

  let output = [];
  do {
    let index = num % radix;
    output.unshift(keys[index]);
    num = Math.trunc(num / radix);
  } while (num != 0);
  if (isNegative) output.unshift('-')
  return output.join("");
}

console.log(toBase("100",2)) 
Nur
  • 2,361
  • 2
  • 16
  • 34
10

Specify the radix you want to use as a parameter.

NOTE: This only works to convert from bases 2-36 to decimal and little values.

parseInt(string, radix) 

parseInt("80", 10) // results in 80
parseInt("80", 16) // results in 128
// etc

About "little", parseInt("6f", 32) is fine (= 207),
but any other little bigger will be also 207, 6f1, 6f11, ...

Peter Krauss
  • 13,174
  • 24
  • 167
  • 304
Russ Cam
  • 124,184
  • 33
  • 204
  • 266
  • @Nosredna you are correct but Russ Cam got the correct syntax for me parseInt - which is more than enough. thanks. – Yves Aug 26 '09 at 20:57
  • 3
    @RussCam I didn't downvote, but I think it's because this answer is limited to converting to decimal, which does address the example given, but the question was `between different bases`. (I have no doubt this has bugged you these six years.) – Antti29 Oct 16 '15 at 08:30
9

Well, I made a function that could translate from base 10 to any base. (This depends on how many strings you have in the array A, if it's more than that + 10 it'll run out of symbols), and I almost cried when I found out you could to it in less than 10 characters with that...

Add a bookmark and as URL insert this... I've done it the long but personal way. At least, mine can use a base which is higher than 36. You can add more symbols yourself, but if you want, I can make it for you...

var X = prompt("Choose your number");
var Y = prompt("Choose your base");
var Z = [];
var M = -1;
var A = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
var B = function() {
    for (i = X; 0 < i; i = Math.floor(i / Y)) { 
        if(i % Y >= 10) { 
            Z.push(A[i % Y - 10]);
        } else { 
            Z.push(i % Y);
        } 
        M = M + 1;
    } 
    for (j = M; j >= 0; j--) {
        document.write(Z[j]);
    } 
};

B(); // Call function
ScienzaM
  • 91
  • 1
  • 1
9

Usually I use this function to convert from different bases.

For example, it returns "11111111" for both cases: convertBase("ff", 16, 2) or convertBase(0xFF, 16, 2)

var convertBase = function(val, base1, base2) {
    if (typeof(val) == "number") {
        return parseInt(String(val)).toString(base2);
    } else {
        return parseInt(val.toString(), base1).toString(base2)
    };
}
Nisarg Shah
  • 14,151
  • 6
  • 34
  • 55
punov
  • 798
  • 7
  • 16
3

I've written a function to convert a JavaScript string from one base to another base, with the original base and the new base specified as parameters.

function convertFromBaseToBase(str, fromBase, toBase){
 var num = parseInt(str, fromBase);
    return num.toString(toBase);
}

alert(convertFromBaseToBase(10, 2, 10));
Anderson Green
  • 30,230
  • 67
  • 195
  • 328
3

This function converts a number from base 10, to an arbitrary base:

function to_base(base, num) {
    const largest_power = ~~(Math.log(num) / Math.log(base));
    const result = [];
    for (let pow = largest_power; pow >= 0; pow--) {
        const digit = ~~(num / base ** pow);
        num -= digit * base ** pow;
        result.push(digit);
    }
    return result;
}

to_base(2, 13) // [1, 1, 0, 1]
to_base(10, 458) // [4, 5, 8]
to_base(32, 1024) // [1, 0, 0]
to_base(32, 1023) // [31, 31]

which can be useful if you want to use weird bases along with weird char-set

2

Using the parseInt function:

var noInBase10 = parseInt('8F',16);
Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151
2

Check the complete JS code to convert into different base

/**
* Convert From/To Binary/Decimal/Hexadecimal in JavaScript
* https://gist.github.com/shamshul2007/
* Copyright 2012-2015, Shamshul <shamshul2007@gmail.com>
* Licensed under The MIT License
* http://www.opensource.org/licenses/mit-license
*/

(function(){

    var ConvertBase = function (num) {
        return {
            from : function (baseFrom) {
                return {
                    to : function (baseTo) {
                        return parseInt(num, baseFrom).toString(baseTo);
                    }
                };
            }
        };
    };
        
    // binary to decimal
    ConvertBase.bin2dec = function (num) {
        return ConvertBase(num).from(2).to(10);
    };
    
    // binary to hexadecimal
    ConvertBase.bin2hex = function (num) {
        return ConvertBase(num).from(2).to(16);
    };
    
    // decimal to binary
    ConvertBase.dec2bin = function (num) {
        return ConvertBase(num).from(10).to(2);
    };
    
    // decimal to hexadecimal
    ConvertBase.dec2hex = function (num) {
        return ConvertBase(num).from(10).to(16);
    };
    
    // hexadecimal to binary
    ConvertBase.hex2bin = function (num) {
        return ConvertBase(num).from(16).to(2);
    };
    
    // hexadecimal to decimal
    ConvertBase.hex2dec = function (num) {
        return ConvertBase(num).from(16).to(10);
    };
    //Octal to Decimal
    ConvertBase.oct2dec = function (num) {
        return ConvertBase(num).from(8).to(10);
    };
    
     //Decimal to Octal
    ConvertBase.dec2oct = function (num) {
        return ConvertBase(num).from(10).to(8);
    };
    
    this.ConvertBase = ConvertBase;
    
})(this);

/*
* Usage example:
* ConvertBase.bin2dec('1111'); // '15'
* ConvertBase.dec2hex('82'); // '52'
* ConvertBase.hex2bin('e2'); // '11100010'
* ConvertBase.dec2bin('153'); // '10011001'
* ConvertBase.hex2dec('1FE4ED63D55FA51E'); //'2298222722903156000'
* ConvertBase.oct2dec('777'); //'511'
* ConvertBase.dec2oct('551'); //'1047'
*/
AlexSp3
  • 2,201
  • 2
  • 7
  • 24
shamshul2007
  • 308
  • 3
  • 15
1

Try the following code, optimised from Slavik Meltser's post, implements BASE n conversions with all the radix combinations between Base2 and Base256. This code accepts three sorts of arguments to define source and destination number systems:

  • by number system radix (e.g. 8)
  • by number system convention name (e.g. 'Bitcoin')
  • by giving custom numerals as an argument (e.g. ['0123456789ABCDEF'])

You'll see that some number system numerals have been hard-coded inside the class and will be used as default when you pass the radix as an argument. (.e.g. 64) When no hard-coded numeral exists (e.g. 16), default numerals are assigned for all radixes ranging between Base2 and Base256, which becomes very clear in the self-test further below.

function BASE() {
  /**
   * BASE n converter doing all the radix combinations between Base2 and Base256
   * @param  {String}               str         input number
   * @param  {Number|String|Array}  fromBase    input number system radix (Number, e.g. 64), convention name (String, e.g. 'Bitcoin') or range (Array)
   * @param  {Number|String|Array}  toBASE      output number system radix (Number), convention name (String) or range (Array e.g. ['0123456789'])
   * @return {String}                           output number
   */
    this.convert = function (str, fromBase, toBASE)
    {
      if(typeof(fromBase)=='object') { this.fromSymbols = fromBase[0] } else this.fromSymbols = this.getsymbols(fromBase);
      if(typeof(toBASE)  =='object') { this.toSymbols = toBASE[0] } else this.toSymbols = this.getsymbols(toBASE);
      fromBase = this.fromSymbols.length; toBASE = this.toSymbols.length;

      // PARSE INPUT DIGITS ARRAY
      for(var _a = [0], str = str.split(''); str.length > 0 && _a[_a.push(this.fromSymbols.indexOf(str.pop())) - 1] >= 0;);
      var _d = _a.shift() + _a[_a.length-1]>=0 ? _a : null; if (_d === null) return null;

      // BASE CONVERSION
      for (var _n = 0,_a = [],_p = [1]; _n < _d.length; _n++) { _a = add(_a, mul(_d[_n], _p, toBASE), toBASE); _p = mul(fromBase, _p, toBASE) }

      // PARSE OUTPUT DIGITS ARRAY
      for (var _n = _a.length - 1, _o = ''; _n >= 0; _o += this.toSymbols[_a[_n--]]);
      return _o.length==0?this.toSymbols[0]:_o;
    }

    this.symbols = {
        32:function(){return this["base32hex"]},
        36:["[0-9][A-Z]"],
        45:function(){return this["qr-alnum"]},
        58:function(){return this["Bitcoin"]},
        64:["[A-Z][a-z][0-9]+/"],
        85:function(){return this["RFC 1924"]},
        91:["[A-Z][a-z][0-9]!#$%&()*+,./:;<=>?@[]^_`{|}~\""],
        94:["[!-~]"],
    "geohash":  ["[0-9][b-h]jkmn[p-z]"],                      // base 32
    "RFC 4648": ["[A-Z][2-7]"],                               // base 32
    "base32hex": ["[0-9][A-V]"],                              // base 32
    "qr-alnum":["[0-9][A-Z] $%*+-./:"],                       // base 45
    "Bitcoin":  ["[1-9][A-H]JKLMN[P-Z][a-k][m-z]"],           // base 58
    "RFC 1924": ["[0-9][A-Z][a-z]!#$%&()*+-;<=>?@^_`{|}~"]    // base 85
    }

    this.getsymbols = function(index) {
      if(typeof(this.symbols[index])=="undefined") this.symbols[index] = index<95?this.rng(index<64?"[0-9][A-Z][a-z]+":"[A-Z][a-z][0-9][!-/][:-@][[-`][{-~]").substring(0,index):this.rng("[\x00-\xff]").substring(256-index,256);
      if(typeof(this.symbols[index])=="function")  this.symbols[index] = this.symbols[index]();             // process references
      if(typeof(this.symbols[index])=="object")    this.symbols[index] = this.rng(this.symbols[index][0]);  // process range_replace
      return this.symbols[index];
    }

    this.rng = function(_s) {
      var _a = _s.match(/\[.-.\]/); if(_a==null) return _s; else { _a=[_a[0].charCodeAt(1),_a[0].charCodeAt(3)];
      return this.rng(_s.replace(RegExp("\\[(\\x"+("0"+_a[0].toString(16)).slice(-2)+"-\\x"+_a[1].toString(16)+")\\]","g")
      ,String.fromCharCode(..." ".repeat(_a[1]-_a[0]+1).split("").map((_e,_i)=>_i+_a[0])) )) }
    }

    this.selftest = function() {
      var _a={}; for(var _o in this.symbols) _a[_o] = this.getsymbols(_o).length; // built-in symbols
      for(_o=2;_o<=95;_o++) _a[_o] = this.getsymbols(_o).length; _a[256]=256;     // symbol range 2-95 + 256 (96-255 is similar)
      var _s = "",_a = Object.keys(_a).sort(function(a,b){return _a[a]-_a[b]});   // sort merged list
      for(var _i in _a) {                                                         // iterate number systems
        _o = {fromBase:10, toBASE:_a[_i]}; var _r = this.convert("",10,_o.toBASE)
        _s += "\r\n\oBASE.convert(n, '"+_o.fromBase+"', '"+_o.toBASE+"') ["+this.fromSymbols+"] ["+this.toSymbols+"]\r\n"
        for(var _n=0;_n<(this.fromSymbols.length+2);_n++) {                       // iterate numbers
          _r = this.convert(String(_n),_o.fromBase,_o.toBASE)
          _s += _n+(String(_n)==this.convert(_r,_o.toBASE,_o.fromBase)?">":"?")+"["+_r+"] ";
        }
      }
      return _s
    }

    var add = function(x, y, base) {
        var _m = Math.max(x.length, y.length);
        for(var _c = _n = 0,_r = []; _n < _m || _c; _c = Math.floor(_z / base)) {
          var _z = _c + (_n < x.length ? x[_n] : 0) + (_n < y.length ? y[_n] : 0);
          var _n =  _r.push(_z % base);
        }
        return _r;
    }

    var mul = function(x, pow, base) {
        for(var _r = x < 0 ? null : []; x > 0; x = x >> 1) {
          if(x & 1) _r = add(_r, pow, base);
          pow = add(pow, pow, base);
        }
        return _r;
    }
}

Usage:

// quick test, convert from base45 to base32, using custom symbols for base85 and back to base45

var oBASE = new BASE();

var n = "THIS IS A NUMBER";                 // Base 45 code = 'qr-alnum'
console.log(n);                             // Result: 'THIS IS A NUMBER'

var n = oBASE.convert(n,"qr-alnum",32);     // Base 45 to Base 32 = 'base32hex'
console.log(n);                             // Result: '4ONI84LCTLJ1U08G1N'

var s85 = oBASE.rng("[0-9][a-z][A-Z].-:+=^!/*?&<>()[]{}@%$#"); // 32/Z85 custom symbols
var n = oBASE.convert(n,"base32hex",[s85]); // 'base2hex' to custom Base 85 
console.log(n);                             // Result: 'fnaxrZP)?5d[DG'

var n = oBASE.convert(n,[s85],45);          // Custom Base 85 to Base 45 = 'qr-alnum'
console.log(n);                             // Result: 'THIS IS A NUMBER'

function BASE(){this.convert=function(o,r,n){this.fromSymbols="object"==typeof r?r[0]:this.getsymbols(r),this.toSymbols="object"==typeof n?n[0]:this.getsymbols(n),r=this.fromSymbols.length,n=this.toSymbols.length;var i=[0];for(o=o.split("");o.length>0&&i[i.push(this.fromSymbols.indexOf(o.pop()))-1]>=0;);var h=i.shift()+i[i.length-1]>=0?i:null;if(null===h)return null;for(var e=0,l=(i=[],[1]);e<h.length;e++)i=t(i,s(h[e],l,n),n),l=s(r,l,n);e=i.length-1;for(var m="";e>=0;m+=this.toSymbols[i[e--]]);return 0==m.length?this.toSymbols[0]:m},this.symbols={32:function(){return this.base32hex},36:["[0-9][A-Z]"],45:function(){return this["qr-alnum"]},58:function(){return this.Bitcoin},64:["[A-Z][a-z][0-9]+/"],85:function(){return this["RFC 1924"]},91:['[A-Z][a-z][0-9]!#$%&()*+,./:;<=>?@[]^_`{|}~"'],94:["[!-~]"],geohash:["[0-9][b-h]jkmn[p-z]"],"RFC 4648":["[A-Z][2-7]"],base32hex:["[0-9][A-V]"],"qr-alnum":["[0-9][A-Z] $%*+-./:"],Bitcoin:["[1-9][A-H]JKLMN[P-Z][a-k][m-z]"],"RFC 1924":["[0-9][A-Z][a-z]!#$%&()*+-;<=>?@^_`{|}~"]},this.getsymbols=function(t){return void 0===this.symbols[t]&&(this.symbols[t]=t<95?this.rng(t<64?"[0-9][A-Z][a-z]+":"[A-Z][a-z][0-9][!-/][:-@][[-`][{-~]").substring(0,t):this.rng("[\0-ÿ]").substring(256-t,256)),"function"==typeof this.symbols[t]&&(this.symbols[t]=this.symbols[t]()),"object"==typeof this.symbols[t]&&(this.symbols[t]=this.rng(this.symbols[t][0])),this.symbols[t]},this.rng=function(t){var s=t.match(/\[.-.\]/);return null==s?t:(s=[s[0].charCodeAt(1),s[0].charCodeAt(3)],this.rng(t.replace(RegExp("\\[(\\x"+("0"+s[0].toString(16)).slice(-2)+"-\\x"+s[1].toString(16)+")\\]","g"),String.fromCharCode(..." ".repeat(s[1]-s[0]+1).split("").map((t,o)=>o+s[0])))))},this.selftest=function(){var t={};for(var s in this.symbols)t[s]=this.getsymbols(s).length;for(s=2;s<=95;s++)t[s]=this.getsymbols(s).length;t[256]=256;var o="";t=Object.keys(t).sort(function(s,o){return t[s]-t[o]});for(var r in t){s={fromBase:10,toBASE:t[r]};var n=this.convert("",10,s.toBASE);o+="\r\noBASE.convert(n, '"+s.fromBase+"', '"+s.toBASE+"') ["+this.fromSymbols+"] ["+this.toSymbols+"]\r\n";for(var i=0;i<this.fromSymbols.length+2;i++)n=this.convert(String(i),s.fromBase,s.toBASE),o+=i+(String(i)==this.convert(n,s.toBASE,s.fromBase)?">":"?")+"["+n+"] "}return o};var t=function(t,s,o){for(var r=Math.max(t.length,s.length),n=e=0,i=[];e<r||n;n=Math.floor(h/o))var h=n+(e<t.length?t[e]:0)+(e<s.length?s[e]:0),e=i.push(h%o);return i},s=function(s,o,r){for(var n=s<0?null:[];s>0;s>>=1)1&s&&(n=t(n,o,r)),o=t(o,o,r);return n}}

Self-Test:

// quick test, convert from base45 to base32, using custom symbols for base85 and back to base45

var oBASE = new BASE();
console.log(oBASE.selftest())  
  
function BASE(){this.convert=function(o,r,n){this.fromSymbols="object"==typeof r?r[0]:this.getsymbols(r),this.toSymbols="object"==typeof n?n[0]:this.getsymbols(n),r=this.fromSymbols.length,n=this.toSymbols.length;var i=[0];for(o=o.split("");o.length>0&&i[i.push(this.fromSymbols.indexOf(o.pop()))-1]>=0;);var h=i.shift()+i[i.length-1]>=0?i:null;if(null===h)return null;for(var e=0,l=(i=[],[1]);e<h.length;e++)i=t(i,s(h[e],l,n),n),l=s(r,l,n);e=i.length-1;for(var m="";e>=0;m+=this.toSymbols[i[e--]]);return 0==m.length?this.toSymbols[0]:m},this.symbols={32:function(){return this.base32hex},36:["[0-9][A-Z]"],45:function(){return this["qr-alnum"]},58:function(){return this.Bitcoin},64:["[A-Z][a-z][0-9]+/"],85:function(){return this["RFC 1924"]},91:['[A-Z][a-z][0-9]!#$%&()*+,./:;<=>?@[]^_`{|}~"'],94:["[!-~]"],geohash:["[0-9][b-h]jkmn[p-z]"],"RFC 4648":["[A-Z][2-7]"],base32hex:["[0-9][A-V]"],"qr-alnum":["[0-9][A-Z] $%*+-./:"],Bitcoin:["[1-9][A-H]JKLMN[P-Z][a-k][m-z]"],"RFC 1924":["[0-9][A-Z][a-z]!#$%&()*+-;<=>?@^_`{|}~"]},this.getsymbols=function(t){return void 0===this.symbols[t]&&(this.symbols[t]=t<95?this.rng(t<64?"[0-9][A-Z][a-z]+":"[A-Z][a-z][0-9][!-/][:-@][[-`][{-~]").substring(0,t):this.rng("[\0-ÿ]").substring(256-t,256)),"function"==typeof this.symbols[t]&&(this.symbols[t]=this.symbols[t]()),"object"==typeof this.symbols[t]&&(this.symbols[t]=this.rng(this.symbols[t][0])),this.symbols[t]},this.rng=function(t){var s=t.match(/\[.-.\]/);return null==s?t:(s=[s[0].charCodeAt(1),s[0].charCodeAt(3)],this.rng(t.replace(RegExp("\\[(\\x"+("0"+s[0].toString(16)).slice(-2)+"-\\x"+s[1].toString(16)+")\\]","g"),String.fromCharCode(..." ".repeat(s[1]-s[0]+1).split("").map((t,o)=>o+s[0])))))},this.selftest=function(){var t={};for(var s in this.symbols)t[s]=this.getsymbols(s).length;for(s=2;s<=95;s++)t[s]=this.getsymbols(s).length;t[256]=256;var o="";t=Object.keys(t).sort(function(s,o){return t[s]-t[o]});for(var r in t){s={fromBase:10,toBASE:t[r]};var n=this.convert("",10,s.toBASE);o+="\r\noBASE.convert(n, '"+s.fromBase+"', '"+s.toBASE+"') ["+this.fromSymbols+"] ["+this.toSymbols+"]\r\n";for(var i=0;i<this.fromSymbols.length+2;i++)n=this.convert(String(i),s.fromBase,s.toBASE),o+=i+(String(i)==this.convert(n,s.toBASE,s.fromBase)?">":"?")+"["+n+"] "}return o};var t=function(t,s,o){for(var r=Math.max(t.length,s.length),n=e=0,i=[];e<r||n;n=Math.floor(h/o))var h=n+(e<t.length?t[e]:0)+(e<s.length?s[e]:0),e=i.push(h%o);return i},s=function(s,o,r){for(var n=s<0?null:[];s>0;s>>=1)1&s&&(n=t(n,o,r)),o=t(o,o,r);return n}}
Shrimpy
  • 174
  • 3
  • 5
1

to convert numbers into different bases in JavaScript or typescript using the following ways.

function binary(number) {
    console.log((number >>> 0).toString(2));   //base 2 for binary
}
binary(-7);

function octal(number) {
    console.log(number.toString(8));   //base 8 for octal
}
octal(15);

function hex(number) {
    console.log(number.toString(16));   //base 16 for hex
}
hex(15);

here in the binary function, you can use number.toString(2) function, but the problem occurs when representing negative numbers. so that you can use the unsigned right shift bitwise operator (>>>) to fix this issue.

Bhavesh Ajani
  • 991
  • 9
  • 11
1

I am writing this answer simply because I was kinda stupid to understand the difference between parseInt and .toString().

Here is the difference

parseInt

parseInt(str, base) will convert the str to an Integer and base here is used to tell parseInt which base the str is in. I thought the base here was what the str would get converted to. But thats not true. parseInt is just used to convert a number in any base to an integer in base10.

.toString()

number.toString(base) is used to convert the number into a number with base base and it assumes that number is in Integer form. So if the number is in hex format and you want to convert it to binary you need to convert the number first to Integer using parseInt and then you can use this function to change the base.

Hope this helps if you are as stupid as me. :)

0

You can also convert number in hexadecimal to decimal as follows:

var a="8F";
var b=a.split("");
var result=0;var hex_multiplier=1;
for(var i=0;i<b.length;i++){
    result +=parseInt(b[i],16)*hex_multiplier;
    hex_multiplier *=16;
}
console.log(result);

where you can change a with any hexadecimal number and get the result in decimal form.

0

You can use JavaScript's built-in integer literals for some scenarios:

function binaryToDecimal(binaryString) {
    return Number('0b' + binaryString.replace('-', '')) * signOf(binaryString);;        
}

function octalToDecimal(octalString) {
    return Number('0o' + octalString.replace('-', '')) * signOf(octalString);
}

function hexToDecimal(hexString) {
    return Number('0x' + hexString.replace('-', '')) * signOf(hexString);
}

function signOf(n) {
  return n.trim()[0] == '-' ? -1 : 1;
}

console.log(binaryToDecimal('-0101'),
             octalToDecimal('-052171'),
               hexToDecimal('deadbeef'));
Mystical
  • 2,505
  • 2
  • 24
  • 43
0

This code converts a number to an arbitrary-large base, outputting an array of digits.

function convertBase(num, base) {
    var result = [];

    while(num >= 1) {
        result.unshift(num % base);
        num = Math.floor(num / base);
    }

    return result;
}

console.log(convertBase(100, 12)); // [8, 4]
console.log(convertBase(5114, 64)); // [1, 15, 58]
Nirvana
  • 405
  • 3
  • 15
0

TypeScript Implementation that supports decimal and int:

class Digit {
  private readonly digitMap: Map<string, number>;

  constructor(readonly digits: string, readonly maxDigits = 10) {
    this.digitMap = new Map<string, number>();

    for (let i = 0; i < digits.length; i += 1) {
      if (digits[i] === ".") {
        throw new TypeError(`Digits should not contain the "." mark.`);
      }

      if (this.digitMap.has(digits[i])) {
        throw new TypeError(`Duplicated digit character.`);
      }

      this.digitMap.set(digits[i], i);
    }
  }

  to = (x: number) => {
    const int = Math.floor(x);
    const dec = x - int;

    let intRemains = int;
    let intResult = "";

    while (true) {
      intResult = this.digits[intRemains % this.digits.length] + intResult;
      intRemains = Math.floor(intRemains / this.digits.length);

      if (intRemains === 0) break;
    }

    if (dec > 0) {
      let decRemains = dec;
      let decResult = "";

      for (let i = 0; i < this.maxDigits; i += 1) {
        const stepCache = decRemains * this.digits.length;
        const decInt = Math.floor(stepCache);
        decResult = decResult + this.digits[decInt];
        decRemains = stepCache - decInt;

        if (decRemains === 0) break;
      }

      if (decResult === "0") return intResult;
      return intResult + "." + decResult;
    }

    return intResult;
  };

  from = (x: string) => {
    const splitted = x.split(".");

    if (splitted.length > 2) return Number.NaN;

    const [int, dec] = splitted;

    let result = 0;

    for (let i = 0; i < int.length; i += 1) {
      const digit = int[int.length - i - 1];

      const oct = this.digitMap.get(digit);
      if (oct === undefined) return Number.NaN;

      result += oct * Math.pow(this.digits.length, i);
    }

    if (dec) {
      for (let i = 0; i < dec.length; i += 1) {
        const digit = dec[i];

        const oct = this.digitMap.get(digit);
        if (oct === undefined) return Number.NaN;

        result += oct * Math.pow(this.digits.length, 0 - i - 1);
      }
    }

    return result;
  };
}

Here're the example about how to use it:

  1. Creating the converter:
const d = new Digit("0123456789");
  1. Convert a number to string:
d.to(1.2345);
  1. Convert a string to number:
d.from("1.2345");

You can also set the second parameter to control the maximum number of decimal places, for example:

const d0 = new Digit("abcdABCD", 10);
d0.to(0.96);
// a.DBdAbcbDcD 

const d1 = new Digit("abcdABCD", 20);
d1.to(0.96);
// a.DBdAbcbDcDacAdCBC 
Losses Don
  • 923
  • 10
  • 14
0

Monkey patched Number prototype for all radixes up to and including 64

( inspired by and derived from @nirvana's answer )

NumberToStringPatched.__patched = NumberToStringPatched;
if (Number.prototype.toString.__patched!==NumberToStringPatched) {
    NumberToStringPatched.__unpatched = Number.prototype.toString;
    Number.prototype.toString = NumberToStringPatched;
}

NumberParseIntPatched.__patched = NumberParseIntPatched;

if (Number.parseInt.__patched!==NumberParseIntPatched) {
    NumberParseIntPatched.__unpatched = Number.parseInt;
    Number.parseInt = NumberParseIntPatched;
}

function NumberToStringPatched(base=10) {
    if (base<33||base>64) return NumberToStringPatched.__unpatched.call(this,base);
    return convertToBase(this,base);
}

function NumberParseIntPatched(str,base=10) {
    if (base<33||base>64) return NumberParseIntPatched.__unpatched.call(this,str,base);
    return convertFromBase(str,base);
}
 
const numberCharSet=(()=>{
    let chars = "0123456789";
       for (let c='a';c<='z';c=String.fromCharCode(c.charCodeAt(0)+1)) {
           chars+=c;
       }
       for (let c='A';c<='Z';c=String.fromCharCode(c.charCodeAt(0)+1)) {
           chars+=c;
       }
       
       return (chars+'_$').split('');
})();

function convertToBase(num, base) {
    var result = '';

    while(num >= 1) {
        result = numberCharSet[num % base]+result;
        num = Math.floor(num / base);
    }

    return result;
}

function convertFromBase(str, base) {
   let charset = numberCharSet.slice(0,base);
   
   if (typeof str==='number') str=str.toString(base);
   if (base <= 26) str=str.toLowerCase();
   
   let digits = str.split('').map(function(c){
       let x = charset.indexOf(c);
       if (x<0) throw new Error("invalid digit for given radix "+base+': '+c);
       return x;
   });

   let result = digits.shift();
   while (digits.length) {
       result=(result*base)+digits.shift();
   }
   return result;
  
}

for (let i = 0;i<64;i++) {
   
   console.log(i.toString(64));
   
}

console.log(9000);
console.log(9 * 10 * 10 * 10);

console.log(0xf000);
console.log(15 * 16 * 16 * 16);

console.log(Number.parseInt('$000',64));
console.log(63 * 64 * 64 * 64);
unsynchronized
  • 4,828
  • 2
  • 31
  • 43
-3

Your Own recursion method for creating base2 conversions.

As mentioned by the users above let n = 13; console.log(n.toString(2)); will result in 13 conversion from base 10 to base 2.

But in case if you want to program the same. I have written a recursive method to do the same. which just simply divide by 2 and then count remainders.

// @author Tarandeep Singh :: Created recursive converter from base 10 to base 2 
// @date : 2017-04-11
// Convert Base 10 to Base 2, We should reverse the output 
// For Example base10to2(10) = "0101" just do res = base10to2(10).split('').reverse().join();
function base10to2(val, res = '') {
  if (val >= 2) {
    res += '' + val % 2;
    return base10to2(val = Math.floor(val / 2), res);
  } else {
    res += '' + 1
    return res;
  }
}

let n = 13;

var result = base10to2(n).split('').reverse().join();
document.write(`Converting ${n} into Base2 is ${result}`);
Tarandeep Singh
  • 1,322
  • 16
  • 16