Uzyskaj dziesiętną część liczby za pomocą JavaScript

248

Mam liczby zmiennoprzecinkowe takie jak 3.2i 1.6.

Muszę oddzielić liczbę na liczbę całkowitą i dziesiętną. Na przykład wartość 3.2będzie podzielona na dwie liczby, tj. 3I0.2

Uzyskanie części całkowitej jest łatwe:

n = Math.floor(n);

Ale mam problem z uzyskaniem części dziesiętnej. Próbowałem tego:

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

Ale nie zawsze działa poprawnie.

Poprzedni kod ma następujące dane wyjściowe:

n = 3.1 => remainer = 1.1

Czego tu brakuje?

Oscar
źródło
1
Zauważ, że n = Math.floor(n);zwraca tylko pożądany wynik (część całkowitą) dla liczb nieujemnych
tsemer
Uprość % 1nie używaj% 2
masterxilo

Odpowiedzi:

366

Użyj 1, nie 2.

js> 2.3 % 1
0.2999999999999998
Ignacio Vazquez-Abrams
źródło
59
W świecie, w którym 0,2999999999999998 jest równe 0,3, może to być dopuszczalne. Dla mnie to nie jest ... Dlatego, aby rozwiązać to wyzwanie, nie będę używać Math.*ani %operacji.
Marcel Stör
62
Aby uniknąć zauważonych problemów z zaokrąglaniem zmiennoprzecinkowym, użycie toFixedmoże pomóc w niektórych sytuacjach, np . (2.3 % 1).toFixed(4)== "0.3000".
Brian M. Hunt
12
(2.3 % 1).toFixed(4).substring(2)= "3000"jeśli potrzebujesz go bez0.
Simon_Weaver
14
W świecie, gdzie liczba 2.3powstał, a nie 2czy 3liczba 0.2999999999999998jest całkowicie dopuszczalne, pomimo jak obrażanie wygląda dla ludzkich oczu.
Gershom
1
@ GershomMaes istnieje wiele okoliczności, w których liczba ta jest nie do przyjęcia.
Adam Leggett,
92
var decimal = n - Math.floor(n)

Chociaż to nie zadziała dla liczb ujemnych, więc być może będziemy musieli to zrobić

n = Math.abs(n); // Change to positive
var decimal = n - Math.floor(n)
Greenimpala
źródło
Jeśli masz już część całkowitą, nie musisz dzwonić Math.floor()ponownie - użyj obliczonej części całkowitej.
tvanfosson
4
var n = 3.2, integr = Math.floor(n), decimal = n - integr;użyj Math.floor () tylko raz. integr = 3; decimal = 0.20000000000000018;
Nurlan
2
Aby pracować z liczby ujemnej, wystarczy zamienić Math.floorz Math.trunc.
Igor Silva,
to zwracało nieprecyzyjną liczbę, taką jak oczekiwałem uzyskać 0,80 ze 100,80, a nie 0,79999 ... Rozwiązałem to, dodając decimal.toFixed (2)
Luis Febro
77

Możesz przekonwertować na ciąg, prawda?

n = (n + "").split(".");
sdleihssirhc
źródło
17
Działa to dobrze wszędzie oprócz Europy kontynentalnej, gdzie przecinek jest separatorem dziesiętnym. Jeśli planujesz skorzystać z tego, pamiętaj, aby wziąć to pod uwagę, jeśli jesteś międzynarodowy i kierujesz swoją ofertę do Europy, ponieważ to rozwiązanie nie zrobi dla nich świetnej roboty.
cdmdotnet,
8
Jestem z Europy kontynentalnej z francuskim Firefoxem i to działa. Zwykle używamy przecinka jako separatora dziesiętnego we Francji. Powodem jest to, że w JavaScript nie ma żadnej kultury podczas konwersji liczby na ciąg, chociaż wolałbym używać n.toString()zamiast, n + ""ponieważ jest bardziej czytelny.
Gabriel Hautclocq,
2
Jeśli prędkość ma kluczowe znaczenie, n + ""to rzeczywiście jest lepsza (patrz jsperf.com/number-vs-number-tostring-vs-string-number )
Gabriel Hautclocq
@cdmdotnet JS używa .jako separatora dziesiętnego, więc wszystko jest w porządku, jeśli typ zmiennej wejściowej jest zmiennoprzecinkowy. Musisz poradzić sobie z tym problemem, tylko jeśli dane wejściowe są ciągiem. Muszę też zauważyć, że ta odpowiedź zwraca ciąg znaków w tablicy. Bardziej kompletnym rozwiązaniem jestparseFloat('0.' + (n + '').split('.')[1])
totymedli
@cdmdotnet Niezależne od lokalizacji rozwiązanie jest tutaj: stackoverflow.com/a/59469716/1742529
user1742529
32

W jaki sposób 0.2999999999999998 jest akceptowalną odpowiedzią? Gdybym był pytającym, chciałbym uzyskać odpowiedź .3. Mamy tutaj fałszywą precyzję, a moje eksperymenty z floor,% itd. Wskazują, że Javascript lubi fałszywą precyzję w tych operacjach. Myślę więc, że odpowiedzi wykorzystujące konwersję na ciąg znaków są na dobrej drodze.

Zrobiłbym to:

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

W szczególności użyłem 100233.1 i chciałem uzyskać odpowiedź „.1”.

jomofrodo
źródło
6
Generalnie się zgadzam, ale nie można polegać na „”. Wyrażenie regularne jako separator dziesiętny jest znakiem i18n .
Marcel Stör
1
@ jomofrodo Właściwie niektórzy mogą chcieć nie zaokrąglonej wartości. Nie przypominam sobie OP z prośbą o zaokrągloną wartość, tylko podzielone wartości.
VVV
1
@VVV tak, niektórzy mogą chcieć nie zaokrągloną wartość. Ale tylko dlatego, że możesz chcieć dokładności do 9 miejsc po przecinku, nie oznacza to, że twoje dane wejściowe faktycznie ją obsługują. Dlatego nazywa się to „fałszywą precyzją”. Jeśli twój wkład to 3.1, najbardziej precyzyjna odpowiedź może mieć dziesiąte, tj. .1. Jeśli odpowiesz na 0,09, oznacza to, że faktycznie obliczyłeś / zmierzyłeś z dokładnością do setnej dokładności, podczas gdy w rzeczywistości oryginalne dane wejściowe były dokładne z dokładnością do dziesiątej.
jomofrodo
1
@ MarcelStör, które można łatwo obsługiwać: var decPart = (n.toLocaleString („en”)). Split („.”) [1];
jem
1
.toString()nie uwzględnia i18n. Separator dziesiętny zawsze będzie . zgodny z MDN i specyfikacją ECMA
Andrewmat
18

Oto jak to robię, co moim zdaniem jest najprostszym sposobem, aby to zrobić:

var x = 3.2;
int_part = Math.trunc(x); // returns 3
float_part = Number((x-int_part).toFixed(2)); // return 0.2
Zantafio
źródło
15

Prostym sposobem na to jest:

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

Niestety nie zwraca to dokładnej wartości. Można to jednak łatwo naprawić:

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

Możesz użyć tego, jeśli nie znasz liczby miejsc dziesiętnych:

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
źródło
9

Niezależny od języka sposób:

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

zwróć uwagę, że jest to poprawne tylko dla liczb o jednej długości fraktalnej)

Nurlan
źródło
3
Czy możesz wyjaśnić, dlaczego uważasz, że jest to niezależny od języka? To jest JavaScript.
najgorętszy
4
@hotzst, nie ma funkcji specyficznej dla języka
Nurlan
1
Niezależny od języka, ponieważ jest to po prostu matematyka. Praktyczne rozwiązanie. O pożądanej długości frakcji:var factor = Math.pow(10, desiredFractionLength); var fract = a * factor % factor / factor;
muratgozel
6

Możesz użyć parseInt()funkcji, aby uzyskać część całkowitą, niż użyć do wyodrębnienia części dziesiętnej

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

Lub możesz użyć wyrażenia regularnego, takiego jak:

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
źródło
decimalPart nadchodzi 0.20000000000000018... to jest naprawdę trudne, ponieważ 0.2 < 0.20000000000000018zwraca true. 3.2 powinno zwrócić 0.2: P robi tyle nieregularności i używa .toFixed(2)łańcucha zwrotów: P
Himanshu Bansal
@HimanshuBansal to problem z JavaScriptem ( zapytaj o to stosu ). Możesz użyć drugiej metody, co zasugerowałem.
Sheki,
Cóż, mam trochę inne zdanie na temat problemu ... W pewnym sensie zastosowałem oba sposoby: P, aby go rozwiązać .. ^^
Himanshu Bansal
@HimanshuBansal cieszę się, że mój post pomógł rozwiązać problem!
Sheki
5

Poniższe działa niezależnie od ustawień regionalnych separatora dziesiętnego ... pod warunkiem, że dla separatora użyty zostanie tylko jeden znak.

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);

To nie jest ładne, ale dokładne.

cdmdotnet
źródło
Jest to oczywiście ciąg, więc możesz potrzebować najpierw parseInt (), jeśli chcesz go jako liczbę. Nie powinieneś potrzebować parseFloat () ... chyba że czegoś brakuje mi tutaj z liczbami podstawowymi 8, a nie podstawowymi 10 ... coś, co niejasno pamiętam sprzed lat
cdmdotnet
5

Jeśli precyzja ma znaczenie i potrzebujesz spójnych wyników, oto kilka propozycji, które zwrócą dziesiętną część dowolnej liczby jako ciąg, w tym wiodące „0”. Jeśli potrzebujesz go jako pływaka, po prostu dodaj var f = parseFloat( result )na końcu.

Jeśli część dziesiętna jest równa zero, zwracane jest „0.0”. Liczby zerowe, NaN i niezdefiniowane nie są testowane.

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");

Oto link jsPerf: https://jsperf.com/decpart-of-number/

Widzimy, że propozycja nr 2 jest najszybsza.

Gabriel Hautclocq
źródło
nie używaj żadnego z nich. pękną, gdy tylko renderowanie liczb przełączy się na inżynierię. nie są również wrażliwe na ustawienia regionalne.
Spongman 30.01.2019
Czy możesz wyjaśnić „przełączanie renderowania liczb na inżynierię”? Ponadto lokalizacja nie jest istotna, ponieważ chcemy tylko części dziesiętnej liczby, a nie zlokalizowanego ciągu reprezentującego liczbę.
Gabriel Hautclocq
4

Możesz przekonwertować go na ciąg i użyć replacemetody, aby zamienić część całkowitą na zero, a następnie przekonwertować wynik z powrotem na liczbę:

var number = 123.123812,
    decimals = +number.toString().replace(/^[^\.]+/,'0');
gion_13
źródło
Czy to rozwiązanie nie zadziałałoby w Europie kontynentalnej, gdzie przecinek jest separatorem dziesiętnym?
Preston
@preston Możesz zamienić kropkę w wyrażeniu regularnym na dowolny znak separatora, który Ci się podoba (np. /^[^,]/), ale powinieneś zostawić wynik jako ciąg znaków (usunąć +operator), aby uniknąć NaNwyników.
gion_13,
4

W zależności od zastosowania, które podasz później, to proste rozwiązanie może ci również pomóc.

Nie twierdzę, że jest to dobre rozwiązanie, ale w niektórych konkretnych przypadkach działa

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

Ale zajmie to więcej czasu niż proponowane rozwiązanie @Brian M. Hunt

(2.3 % 1).toFixed(4)
David Sánchez
źródło
1
Działa to dobrze wszędzie oprócz Europy kontynentalnej, gdzie przecinek jest separatorem dziesiętnym. Jeśli planujesz skorzystać z tego, pamiętaj, aby wziąć to pod uwagę, jeśli jesteś międzynarodowy i kierujesz swoją ofertę do Europy, ponieważ to rozwiązanie nie zrobi dla nich świetnej roboty.
cdmdotnet,
1

Miałem przypadek, w którym wiedziałem, że wszystkie omawiane liczby będą miały tylko jedną dziesiętną, i chciałem uzyskać część dziesiętną jako liczbę całkowitą, więc ostatecznie zastosowałem takie podejście:

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

Działa to również dobrze z liczbami całkowitymi, zwracając w takich przypadkach 0.

peksipatongeis
źródło
1

Ja używam:

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]);
}

Dane wejściowe: -556,123444444

Wynik: 123444444

DavidDunham
źródło
1

Funkcje matematyczne są szybsze, ale zawsze zwracają nie natywne oczekiwane wartości. Najłatwiejszy sposób, jaki znalazłem to

(3.2+'').replace(/^[-\d]+\./, '')
Vasilii Suricov
źródło
1

Dobrą opcją jest przekształcenie liczby w ciąg, a następnie podzielenie.

// 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

W jednym wierszu kodu

let [firstNumber, secondNumber] = [+number.toString().split('.')[0], +number.toString().split('.')[1]];
Erik Martín Jordán
źródło
0

Po przejrzeniu kilku z nich używam teraz ...

var rtnValue = Number(7.23);
var tempDec = ((rtnValue / 1) - Math.floor(rtnValue)).toFixed(2);
Patrick
źródło
0
n = Math.floor(x);
remainder = x % 1;
masterxilo
źródło
0

Chociaż jestem bardzo późno, aby odpowiedzieć na to pytanie, proszę spojrzeć na kod.

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
źródło
0

Format znaku i liczby zmiennoprzecinkowej może być zależny od country ( .,), więc niezależne rozwiązanie, które zachowało część zmiennoprzecinkową, to:

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

- jest to rozwiązanie międzynarodowe, a nie zależne od lokalizacji:

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

Opis rozwiązania krok po kroku:

  1. parseFloat() dla zagwarantowania korekcji wejściowej
  2. Math.abs() dla uniknięcia problemów z liczbami ujemnymi
  3. n = parseInt(x) za uzyskanie części dziesiętnej
  4. x - n do odejmowania części dziesiętnej
  5. Mamy teraz liczbę z zerową częścią dziesiętną, ale JavaScript może dać nam dodatkowe cyfry części ruchomej, których nie chcemy
  6. Tak więc ogranicz dodatkowe cyfry, dzwoniąc toFixed()z liczbą cyfr w ruchomej części oryginalnego numeru zmiennoprzecinkowego x. Liczba jest obliczana jako różnica między długością oryginalnej liczby xa liczbą nw ich reprezentacji ciągu.
użytkownik1742529
źródło
-1

Użyj tego:

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;
      }    
  }

Math.fracFunkcja tutaj ma 3 tryby pracy:

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 (%)

To proste :)

Mr_DJA
źródło
-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
użytkownik2381223
źródło
4
dla mnie to nie wygląda na javascript!
Ch'marr,
1
To nie jest skrypt Java
Amrut,
W JS powinno to wyglądać tak: var a = 3.2; var b = parseInt (a, 10); var c = a - b;
Ju-v