Javascript tiene la función parseInt() que puede ayudar a convertir un entero en forma binaria en su equivalente decimal:

parseInt("101", 2) // 5

Sin embargo, necesito convertir la fracción binaria a su equivalente decimal, como:

0.101 = 0.625

Puedo escribir mi propia función que calcularía el resultado de la siguiente manera:

1 * Math.pow(2, -1) + 0*Math.pow(2, -2) + 1*Math.pow(2, -3) // 0.625

Pero me pregunto si ya hay algo estándar.

23
Max Koretskyi 9 may. 2016 a las 10:28

6 respuestas

La mejor respuesta

Puede dividir el número (como cadena) en el punto y tratar la parte entera con una función propia y la parte fraccionada con otra función para el valor correcto.

La solución también funciona con otras bases.

function convert(value, base = 2) {
    var [integer, fraction = ''] = value.toString().split('.');

    return parseInt(integer, base) + (integer[0] !== '-' || -1) * fraction
        .split('')
        .reduceRight((r, a) => (r + parseInt(a, base)) / base, 0);
}

console.log(convert(1100));           //    12
console.log(convert(0.0011));         //     0.1875
console.log(convert(1100.0011));      //    12.1875

console.log(convert('ABC', 16));      //  2748
console.log(convert('0.DEF', 16));    //     0.870849609375
console.log(convert('ABC.DEF', 16));  //  2748.870849609375

console.log(convert('-ABC.DEF', 16)); // -2748.870849609375
console.log(convert(-1100.0011));     //   -12.1875
.as-console-wrapper { max-height: 100% !important; top: 0; }
10
Nina Scholz 8 nov. 2019 a las 13:41

Pero me pregunto si ya hay algo estándar.

No según mi conocimiento

Creo que necesitas crear tu propia función:

  function toDecimal(string, radix) {
    radix = radix || 2;
    var s = string.split('.');
    var decimal = parseInt(s[0], radix);

    if(s.length > 1){
       var fract = s[1].split('');

       for(var i = 0, div = radix; i < fract.length; i++, div = div * radix) {
          decimal = decimal + fract[i] / div;
       }
    }
    return decimal;
  }
3
granmirupa 9 may. 2016 a las 07:41

Puede crear un método de extensión de JavaScript como parseInt ya que he creado el método parseBinary que funciona solo con el enlace parseInt.

String.prototype.parseBinary = function parseBinary() {
  var radix = 2;
  var s = this.split('.');
  var decimal = parseInt(s[0], radix);

  if(s.length > 1){
    var fract = s[1].split('');

    for(var i = 0, div = radix; i < fract.length; i++, div = div * radix)
    {
      decimal = decimal + fract[i] / div;
    }
  }
  return decimal;
};

Para usar este método, puede llamarlo usando el siguiente código.

var str = "0.101";
alert(str.parseBinary());

Aquí hay un ejemplo funcional de código javascript

String.prototype.parseBinary = function parseBinary() {
  var radix = 2;
  var s = this.split('.');
  var decimal = parseInt(s[0], radix);

  if(s.length > 1){
    var fract = s[1].split('');

    for(var i = 0, div = radix; i < fract.length; i++, div = div * radix)
    {
      decimal = decimal + fract[i] / div;
    }
  }
  return decimal;
};

var str = "0.101";
alert(str.parseBinary());
2
Umar Abbas 9 may. 2016 a las 08:12

Mi lógica detrás es parseInt(res[0] + res[1], base) / Math.pow(base, res[1].length);

Ej: var fValue = '-1100.0011'; resultado var = parseInt ('- 11000011', base) / Math.pow (base, '0011'.length);

<script>
    parseFractionInt = (value, base = 2) => {
        var res = value.split('.');
        return res.length < 2 ? 
                parseInt(value, base) : 
                parseInt(res[0] + res[1], base) / Math.pow(base, res[1].length);
    }

    console.log(parseFractionInt('0.101'));  //0.625
    console.log(parseFractionInt('1100'));           //    12
    console.log(parseFractionInt('0.0011'));         //     0.1875
    console.log(parseFractionInt('1100.0011'));      //    12.1875

    console.log(parseFractionInt('ABC', 16));      //  2748
    console.log(parseFractionInt('0.DEF', 16));    //     0.870849609375
    console.log(parseFractionInt('ABC.DEF', 16));  //  2748.870849609375

    console.log(parseFractionInt('-ABC.DEF', 16)); // -2748.870849609375
    console.log(parseFractionInt('-1100.0011'));    //   -12.1875
    console.log(parseFractionInt('G.G', 16));   //NaN
    console.log(parseFractionInt('A.G', 16));   //0.625

</script>
2
Prabhat 10 nov. 2019 a las 07:52

TL; DR :

const convert = (s, b) => (+((s = s.toString().trim().split("."))[0][0] !== "-") || -1) * ((parseInt(s[0].replace("-", ""), (b = +b || 2))) + (s[1].split("").reduceRight((n, d) => (n + parseInt(d, b)) / b, 0)));

Nina Scholz tiene un buen ejemplo, pero no funciona con números negativos (más otros problemas).
Entonces, este es uno mejorado:

/**
 * @param {string} input
 * @param {number} [base]
 * @returns {number}
 */
function convert(input, base = 2) {
    const [ integerRaw, decimalRaw = "" ] = input.toString().trim().split(".");

    const integer = parseInt(integerRaw.replace("-", ""), base);
    const decimal = decimalRaw.split("").reduceRight((sum, num) => (sum + parseInt(num, base)) / base, 0);

    return (integerRaw.startsWith("-") ? -1 : 1) * (integer + decimal);
}

convert("1100.0011"); // 12.1875
convert("-1100.0011"); // -12.1875
convert("-Z.ZZZ", 36); // -35.99997856652949

Como sé, JavaScript no proporciona dicha funcionalidad incorporada.

6
Dmitry Parzhitsky 12 nov. 2019 a las 10:51

Esta pregunta pregunta si hay algún estándar de JavaScript para analizar números de punto flotante binarios, como si parseFloat() pudiera haber tomado un segundo parámetro de raíz para analizar el número binario 0.101 de esta manera: parseFloat('0.101', 2).

Si bien no existe dicho estándar, existe una manera fácil y directa de resolverlo.

Si representamos el número binario 0.101 como una fracción binaria, se convierte fácilmente en una fracción decimal:

0.101 2 = 101 2 / 1000 2 = (5/8) 10 = 0.625

La siguiente expresión de una línea traduce esto a JavaScript. Aquí, num podría ser cualquier tipo de número binario (representado como una cadena), incluidos los números negativos:

parseInt(num.replace('.', ''), 2) / Math.pow(2, (num.split('.')[1] || '').length)

La solución se adapta fácilmente a los números de coma flotante en cualquier base entre 2 y 36, y podemos envolverla en nuestra propia función parseFloatRadix():

function parseFloatRadix(num, radix) {
  return parseInt(num.replace('.', ''), radix) /
    Math.pow(radix, (num.split('.')[1] || '').length)
}

test('0.101',  2, 0.625);
test('0.011',  2, 0.375);
test('0.0011', 2, 0.1875);
test('-011',   2, -3);
test('011',    2,  3);
test('-1100.0011', 2, -12.1875);
test('1100.0011',  2,  12.1875);
test('0.00011001100110011001100', 2, 0.09999990463256836);

test('ABC',     16, 2748);
test('-0.DEF',  16, -0.870849609375);
test('ABC.DEF', 16, 2748.870849609375);

test('-102.201', 3, -11.703703703703704);
test('-Z.ZZZ',  36, -35.99997856652949);

function test(num, radix, expected){
  let result = parseFloatRadix(num, radix);
  console.log(num + ' (base ' + radix +') --> ' + result + 
    (result === expected ? ' (OK)' : ' (Expected ' + expected + ')'));
}
9
Tomas Langkaas 9 nov. 2019 a las 22:21