Obter parte decimal de um número com JavaScript

247

Eu tenho números flutuantes como 3.2e 1.6.

Preciso separar o número na parte inteira e decimal. Por exemplo, um valor de 3.2seria dividido em dois números, ie 3e0.2

Obter a parte inteira é fácil:

n = Math.floor(n);

Mas estou tendo problemas para obter a parte decimal. Eu tentei isso:

remainer = n % 2; //obtem a parte decimal do rating

Mas nem sempre funciona corretamente.

O código anterior tem a seguinte saída:

n = 3.1 => remainer = 1.1

O que estou perdendo aqui?

Oscar
fonte
1
Observe que n = Math.floor(n);só é devolver o resultado desejado (a parte inteira) para números não negativos
tsemer
Simplfy use % 1not% 2
masterxilo 19/10/19

Respostas:

367

Use 1, não 2.

js> 2.3 % 1
0.2999999999999998
Ignacio Vazquez-Abrams
fonte
59
Em um mundo em que 0,2999999999999998 é igual a 0,3, isso pode ser aceitável. Para mim, não é ... Portanto, para resolver esse desafio, eu evitaria usar Math.*ou %operar.
Marcel Stör
62
Para evitar os problemas de arredondamento de ponto flutuante observados, o uso toFixedpode ajudar em algumas situações, por exemplo, (2.3 % 1).toFixed(4)== "0.3000".
Brian M. Caça
12
(2.3 % 1).toFixed(4).substring(2)= "3000"Se você precisar dele, sem a0.
Simon_Weaver
14
Em um mundo em que o número 2.3surgiu, e não 2ou 3, o número 0.2999999999999998é perfeitamente aceitável, apesar de parecer ofensivo aos olhos humanos.
Gershom
1
@GershomMaes, existem várias circunstâncias em que esse número não é aceitável.
Adam Leggett
92
var decimal = n - Math.floor(n)

Embora isso não funcione para números negativos, talvez tenhamos que fazer

n = Math.abs(n); // Change to positive
var decimal = n - Math.floor(n)
greenimpala
fonte
Se você já possui a parte inteira, não há necessidade de ligar Math.floor()novamente - basta usar a parte inteira que você calculou.
tvanfosson
4
var n = 3.2, integr = Math.floor(n), decimal = n - integr;use Math.floor () apenas uma vez. integr = 3; decimal = 0.20000000000000018;
Nurlan
2
Para trabalhar com número negativo, basta trocar Math.floorcom Math.trunc.
Igor Silva
isso estava retornando um número não exato, como eu esperava obter 0,80 de 100,80, não 0,79999 ... Eu resolvi isso adicionando decimal.toFixed (2)
Luis Febro
76

Você pode converter para string, certo?

n = (n + "").split(".");
sdleihssirhc
fonte
17
Isso funciona bem em todos os lugares, exceto na Europa continental, onde uma vírgula é o separador decimal. Se você planeja usar isso, lembre-se de levar isso em consideração se for multinacional e tiver como alvo a europa, pois essa solução não fará um ótimo trabalho para eles.
Cdmdotnet 17/06/2015
8
Eu sou da Europa continental com um Firefox francês e funciona. Normalmente usamos a vírgula como separador decimal na França. A razão é que, no JavaScript, não há cultura envolvida na conversão de um número em string, embora eu prefira usá-lo em n.toString()vez de n + ""ser mais legível.
Gabriel Hautclocq
2
Se a velocidade é fundamental, em seguida, n + ""é realmente melhor (ver jsperf.com/number-vs-number-tostring-vs-string-number )
Gabriel Hautclocq
O @cdmdotnet JS usa .como um separador decimal, assim você estará bem em qualquer lugar se o tipo da sua variável de entrada for flutuante. Você só precisa lidar com esse problema se sua entrada for string. Eu também tenho que observar que esta resposta retorna uma string em uma matriz. Uma solução mais completa éparseFloat('0.' + (n + '').split('.')[1])
totymedli 30/03/19
A solução independente de localização do @cdmdotnet está aqui: stackoverflow.com/a/59469716/1742529
user1742529
32

Como 0.2999999999999998 é uma resposta aceitável? Se eu fosse o autor da pergunta, gostaria de receber uma resposta de 0,3. O que temos aqui é precisão falsa, e meus experimentos com floor,%, etc indicam que o Javascript gosta de precisão falsa para essas operações. Então, acho que as respostas que estão usando a conversão para string estão no caminho certo.

Eu faria isso:

var decPart = (n+"").split(".")[1];

Especificamente, eu estava usando 100233.1 e queria a resposta ".1".

jomofrodo
fonte
6
Eu geralmente concordo, mas você não pode confiar em '.' o regex como separador decimal é um caractere i18n .
Marcel Stör
1
@jomofrodo Na verdade, alguns podem querer o valor não arredondado. Não me lembro do OP pedindo um valor arredondado, apenas dividindo valores.
VVV
1
@VVV sim, alguns podem querer o valor não arredondado. Mas apenas porque você pode querer precisão de 9 casas decimais não significa que seus dados de entrada realmente os suportam. É por isso que é chamado de "precisão falsa". Se sua entrada é 3.1, a maior precisão que sua resposta pode ter é décimos, ou seja, .1. Se você responder .09, isso implica que você realmente calculou / mediu com precisão de centésimos, quando na verdade a entrada original era precisa apenas com precisão de décimos.
jomofrodo
1
@ MarcelStör que pode ser facilmente manipulado: var decPart = (n.toLocaleString ("en")). Split (".") [1];
jem
1
.toString()não considera i18n. O separador decimal será sempre de . acordo com o MDN e as especificações da ECMA
Andrewmat 14/04
18

Aqui está como eu faço, que eu acho que é a maneira mais direta de fazê-lo:

var x = 3.2;
int_part = Math.trunc(x); // returns 3
float_part = Number((x-int_part).toFixed(2)); // return 0.2
Zantafio
fonte
15

Uma maneira simples de fazer isso é:

var x = 3.2;
var decimals = x - Math.floor(x);
console.log(decimals); //Returns 0.20000000000000018

Infelizmente, isso não retorna o valor exato. No entanto, isso é facilmente corrigido:

var x = 3.2;
var decimals = x - Math.floor(x);
console.log(decimals.toFixed(1)); //Returns 0.2

Você pode usar isso se não souber o número de casas decimais:

var x = 3.2;
var decimals = x - Math.floor(x);

var decimalPlaces = x.toString().split('.')[1].length;
decimals = decimals.toFixed(decimalPlaces);

console.log(decimals); //Returns 0.2

Ethan
fonte
9

Maneira independente da língua:

var a = 3.2;
var fract = a * 10 % 10 /10; //0.2
var integr = a - fract; //3

observe que ele corrige apenas números com um comprimento fraturaanal)

Nurlan
fonte
3
Você pode explicar por que você acha que isso é independente da linguagem? É JavaScript.
hotzst
4
@hotzst, não há nenhuma função linguagem específica
Nurlan
1
Independente da linguagem porque é apenas matemática pura. Solução prática. Com comprimento de fração desejado:var factor = Math.pow(10, desiredFractionLength); var fract = a * factor % factor / factor;
muratgozel
6

Você pode usar a parseInt()função para obter a parte inteira do que a extrair a parte decimal

var myNumber = 3.2;
var integerPart = parseInt(myNumber);
var decimalPart = myNumber - integerPart;

Ou você pode usar regex como:

splitFloat = function(n){
   const regex = /(\d*)[.,]{1}(\d*)/;
   var m;

   if ((m = regex.exec(n.toString())) !== null) {
       return {
          integer:parseInt(m[1]),
          decimal:parseFloat(`0.${m[2]}`)
       }
   }
}
Sheki
fonte
decimalPart está chegando 0.20000000000000018... isso é realmente ficando difícil de fazer porque 0.2 < 0.20000000000000018retorna true .. 3.2 deve retornar 0,2: P fazendo tantas irregularidades e usando .toFixed(2)retornos string: P
Himanshu Bansal
@HimanshuBansal, esse é um problema de JavaScript (faça uma pergunta sobre o stackeoverflow ). Você pode usar o segundo método que sugeri.
Sheki
Bem, eu tenho uma declaração de problema um pouco diferente ... meio que usei as duas maneiras: P para resolvê-lo .. ^^
Himanshu Bansal
@HimanshuBansal feliz que meu post tenha ajudado a resolver seu problema!
Sheki
5

O seguinte funciona, independentemente das configurações regionais do separador decimal ... na condição de apenas um caractere ser usado para um separador.

var n = 2015.15;
var integer = Math.floor(n).toString();
var strungNumber = n.toString();
if (integer.length === strungNumber.length)
  return "0";
return strungNumber.substring(integer.length + 1);

Não é bonito, mas é preciso.

cdmdotnet
fonte
É claro que isso é uma string, então você pode precisar primeiro analisar parseInt () se quiser como um número. Você não precisa parseFloat () ... a menos que haja algo que eu sinto falta aqui com base de 8 não-base 10 números ... algo que eu me lembro vagamente de anos atrás
cdmdotnet
5

Se a precisão for importante e você precisar de resultados consistentes, aqui estão algumas proposições que retornarão a parte decimal de qualquer número como uma string, incluindo o "0" inicial. Se você precisar dele como flutuador, basta adicionar var f = parseFloat( result )no final.

Se a parte decimal for igual a zero, "0,0" será retornado. Nulo, NaN e números indefinidos não são testados.

1. String.split

var nstring = (n + ""),
    narray  = nstring.split("."),
    result  = "0." + ( narray.length > 1 ? narray[1] : "0" );

2. String.substring, String.indexOf

var nstring = (n + ""),
    nindex  = nstring.indexOf("."),
    result  = "0." + (nindex > -1 ? nstring.substring(nindex + 1) : "0");

3. Math.floor, Number.toFixed, String.indexOf

var nstring = (n + ""),
    nindex  = nstring.indexOf("."),
    result  = ( nindex > -1 ? (n - Math.floor(n)).toFixed(nstring.length - nindex - 1) : "0.0");

4. Math.floor, Number.toFixed, String.split

var nstring = (n + ""),
    narray  = nstring.split("."),
    result  = (narray.length > 1 ? (n - Math.floor(n)).toFixed(narray[1].length) : "0.0");

Aqui está um link jsPerf: https://jsperf.com/decpart-of-number/

Podemos ver que a proposição nº 2 é a mais rápida.

Gabriel Hautclocq
fonte
não use nenhum deles. eles quebrarão assim que a renderização do número mudar para a engenharia. eles também não são sensíveis ao local.
Spongman
Você poderia explicar "a renderização numérica alterna para engenharia"? Além disso, a localização não é relevante porque queremos apenas a parte decimal de um número, não uma sequência localizada que representa um número.
Gabriel Hautclocq
4

Você pode convertê-lo em uma sequência e usar o replacemétodo para substituir a parte inteira por zero, depois converter o resultado novamente em um número:

var number = 123.123812,
    decimals = +number.toString().replace(/^[^\.]+/,'0');
gion_13
fonte
Essa solução não funcionaria na Europa continental, onde vírgula é o separador decimal?
Preston
@preston Você pode substituir o ponto no regex por qualquer outro caractere separador que desejar (como /^[^,]/), mas deve deixar o resultado como uma string (remover o +operador) para evitar NaNresultados.
gion_13
4

Dependendo do uso que você fornecerá posteriormente, mas esta solução simples também poderá ajudá-lo.

Não estou dizendo que é uma boa solução, mas para alguns casos concretos funciona

var a = 10.2
var c = a.toString().split(".")
console.log(c[1] == 2) //True
console.log(c[1] === 2)  //False

Mas levará mais tempo do que a solução proposta por @Brian M. Hunt

(2.3 % 1).toFixed(4)
David Sánchez
fonte
1
Isso funciona bem em todos os lugares, exceto na Europa continental, onde uma vírgula é o separador decimal. Se você planeja usar isso, lembre-se de levar isso em consideração se for multinacional e tiver como alvo a europa, pois essa solução não fará um ótimo trabalho para eles.
Cdmdotnet
1

Eu tive um caso em que sabia que todos os números em questão teriam apenas um decimal e queria obter a parte decimal como um número inteiro, então acabei usando esse tipo de abordagem:

var number = 3.1,
    decimalAsInt = Math.round((number - parseInt(number)) * 10); // returns 1

Isso funciona bem também com números inteiros, retornando 0 nesses casos.

peksipatongeis
fonte
1

Estou usando:

var n = -556.123444444;
var str = n.toString();
var decimalOnly = 0;

if( str.indexOf('.') != -1 ){ //check if has decimal
    var decimalOnly = parseFloat(Math.abs(n).toString().split('.')[1]);
}

Entrada: -556.123444444

Resultado: 123444444

DavidDunham
fonte
1

As funções matemáticas são mais rápidas, mas sempre retornam valores não nativos esperados. A maneira mais fácil que encontrei é

(3.2+'').replace(/^[-\d]+\./, '')
Vasilii Suricov
fonte
1

Uma boa opção é transformar o número em uma string e depois dividi-lo.

// Decimal number
let number = 3.2;

// Convert it into a string
let string = number.toString();

// Split the dot
let array = string.split('.');

// Get both numbers
// The '+' sign transforms the string into a number again
let firstNumber  = +array[0]; // 3
let secondNumber = +array[1]; // 2

Em uma linha de código

let [firstNumber, secondNumber] = [+number.toString().split('.')[0], +number.toString().split('.')[1]];
Erik Martín Jordán
fonte
0

Depois de analisar várias delas, agora estou usando ...

var rtnValue = Number(7.23);
var tempDec = ((rtnValue / 1) - Math.floor(rtnValue)).toFixed(2);
Patrick
fonte
0
n = Math.floor(x);
remainder = x % 1;
masterxilo
fonte
0

Embora eu esteja muito atrasado para responder, dê uma olhada no código.

let floatValue = 3.267848;
let decimalDigits = floatValue.toString().split('.')[1];
let decimalPlaces = decimalDigits.length;
let decimalDivider = Math.pow(10, decimalPlaces);
let fractionValue = decimalDigits/decimalDivider;
let integerValue = floatValue - fractionValue;

console.log("Float value: "+floatValue);
console.log("Integer value: "+integerValue);
console.log("Fraction value: "+fractionValue)
Hifzur Rahman
fonte
0

O sinal decimal em ponto flutuante e o formato numérico podem depender do país ( .,); portanto, a solução independente, que preservou a parte do ponto flutuante, é:

getFloatDecimalPortion = function(x) {
    x = Math.abs(parseFloat(x));
    let n = parseInt(x);
    return Number((x - n).toFixed(Math.abs((""+x).length - (""+n).length - 1)));
}

- é uma solução internacionalizada, em vez de depender da localização:

getFloatDecimalPortion = x => parseFloat("0." + ((x + "").split(".")[1]));

Descrição da solução passo a passo:

  1. parseFloat() para garantir a criptografia de entrada
  2. Math.abs() para evitar problemas com números negativos
  3. n = parseInt(x) para obter parte decimal
  4. x - n para subtrair parte decimal
  5. Agora, temos um número com zero parte decimal, mas o JavaScript pode nos fornecer dígitos adicionais flutuantes, o que não queremos
  6. Portanto, limite dígitos adicionais chamando toFixed()com a contagem de dígitos na parte flutuante do número flutuante original x. A contagem é calculada como a diferença entre o comprimento do número original xe o número nem sua representação de sequência.
user1742529
fonte
-1

Use este:

function isNatural(n) {
    n = +n
    if (isNaN(n)) return 'NaN';
    return (n >= 0.0) && (Math.floor(n) === n) && n !== Infinity;
  }

Math.frac = function frac(x, m) {
    x = +x
    if (isNaN(x)) return NaN;
    if (isNatural(x) === true) return 0;
    m = +m || 1

      if (isNatural(x) === false && m === 1){
        var a = x.toString()
        var b = a.split('.')[1]
        var c = '0.' + b
        var d = +c
        return d;
      }

      if (isNatural(x) === false && m === 2){
        var a = x.toString()
        var b = a.split('.')[1]
        var c = +b
        return c;
      }

      if (isNatural(x) === false && m === 3){
        var a = x.toString()
        var b = a.split('.')[1]
        var c = '0.' + b
        var d = +c * 100
        return d;
      }    
  }

A Math.fracfunção aqui tem 3 modos:

Math.frac(11.635) //0.635
Math.frac(11.635, 1) //0.635 - default mode is 1
Math.frac(11.635, 2) //635
Math.frac(11.635, 3) //63,5 (%)

É simples :)

Mr_DJA
fonte
-9
float a=3.2;
int b=(int)a; // you'll get output b=3 here;
int c=(int)a-b; // you'll get c=.2 value here
user2381223
fonte
4
que não me parece javascript!
Ch'marr 8/08/13
1
Este não é java script
Amrut
Em JS, deve ser como: var a = 3.2; var b = parseInt (a, 10); var c = a - b;
/