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?


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

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)

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

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”.


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

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


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)


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

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.


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.


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

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)

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.


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


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]+\./, '')

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

0

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

var rtnValue = Number(7.23);
var tempDec = ((rtnValue / 1) - Math.floor(rtnValue)).toFixed(2);


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)

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.

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


-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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.