Tronca il numero al secondo decimale senza arrotondare


196

Supponiamo di avere un valore di 15.7784514, voglio visualizzarlo 15.77 senza arrotondamento.

var num = parseFloat(15.7784514);
document.write(num.toFixed(1)+"<br />");
document.write(num.toFixed(2)+"<br />");
document.write(num.toFixed(3)+"<br />");
document.write(num.toFixed(10));

Risultati in -

15.8
15.78
15.778
15.7784514000 

Come visualizzo 15.77?


3
Sono tentato di chiedere, perché non vuoi arrotondare? Sembra errato, non importa dove ...
Camilo Martin,

39
È utile quando si visualizza la valuta.
Richard Ye,

@ mik01aj: quando si visualizza la valuta, è più comune troncare i valori calcolati anziché arrotondarli. Ad esempio, la maggior parte dei moduli fiscali negli Stati Uniti tronca anziché arrotondare i centesimi frazionari calcolati. In tal caso, il valore troncato è il valore corretto.
Steven Byks

4
@CamiloMartin c'è un'enorme differenza tra un debito di 1,49 miliardi di dollari e 1,0 miliardi di dollari.
Broda Noel,

3
C'è anche un'enorme differenza tra 1,49 miliardi e 1,50 miliardi di dollari. Sono $ 100 milioni.
Liga,

Risposte:


228

Converti il ​​numero in una stringa, abbina il numero fino al secondo decimale:

function calc(theform) {
    var num = theform.original.value, rounded = theform.rounded
    var with2Decimals = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)[0]
    rounded.value = with2Decimals
}
<form onsubmit="return calc(this)">
Original number: <input name="original" type="text" onkeyup="calc(form)" onchange="calc(form)" />
<br />"Rounded" number: <input name="rounded" type="text" placeholder="readonly" readonly>
</form>

Il toFixedmetodo non riesce in alcuni casi a differenza toString, quindi fai molta attenzione.


22
+1 Questo dovrebbe risolvere il problema di arrotondamento. Sarei ancora uscita il risultato di quanto sopra utilizzando toFixed, però, così: (Math.floor(value * 100) / 100).toFixed(2). Come probabilmente saprai, possono accadere strane cose di precisione con valori in virgola mobile (e dall'altro lato dello spettro, se il numero risulta essere 15, suona come l'OP vuole 15.00).
TJ Crowder,

1
hehe, o se si combinano entrambi:Number((15.7784514000*100).toString().match(/^\d+/)/100);
skobaljic,

27
Math.floor (valore * 100) / 100 non funzionerà se value = 4.27 sul serio, provalo.
Ippopotamo scuro,

3
@DarkHippo Questo perché 4.27 è in realtà 4.26999999999, Math.round è generalmente una soluzione migliore, sebbene non la risposta alla domanda originale. Realisticamente dato che l'output è una stringa, questo dovrebbe essere fatto usando la manipolazione di stringhe invece di una soluzione numerica con tutti i difetti in virgola mobile.
Giuria

3
... non suona bene. La conversione tra i tipi in qualsiasi circostanza sembra rotonda e non sicura. A meno che un programmatore veramente avanzato non sostenga che "tutti i tipi sono solo flussi" o qualcosa del genere.
JackHasaTastiera

66

Aggiornamento 5 nov 2016

Nuova risposta, sempre accurata

function toFixed(num, fixed) {
    var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
    return num.toString().match(re)[0];
}

Poiché la matematica in virgola mobile in JavaScript avrà sempre casi limite, la soluzione precedente sarà accurata per la maggior parte del tempo, il che non è abbastanza buono. Ci sono alcune soluzioni a questo come num.toPrecision, BigDecimal.js e accounting.js . Tuttavia, credo che il semplice analisi della stringa sarà la più semplice e sempre accurata.

Basando l'aggiornamento sulla regex ben scritta dalla risposta accettata da @Gumbo, questa nuova funzione toFixed funzionerà sempre come previsto.


Vecchia risposta, non sempre accurata.

Passa alla tua funzione fissa:

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}

7
toFixed (4.56, 2) = 4.55
cryss

2
Molte di queste risposte hanno una moltiplicazione all'interno di una funzione Math.floor (). Questo fallirà per alcuni numeri! L'aritmetica in virgola mobile non è precisa ed è necessario utilizzare metodi diversi.
Nico Westerdale,

1
funzione toFixedCustom (num, fixed) {var re = new RegExp ('^ -? \\ d + (?: \. \\ d {0,' + (fixed || -1) + '})?'); if (num.toString (). match (re)) {return num.toString (). match (re) [0]; }}
Ryan Augustine,

1
La risposta aggiornata non riuscirà per un numero abbastanza grande o piccolo che javascript rappresenterebbe nella notazione scientifica. toFixed(0.0000000052, 2)restituisce "5,2". Questo può essere risolto usando return num.toFixed(fixed+1).match(re)[0];Notice Sto usando toFixed con una cifra decimale sopra il target per evitare arrotondamenti, quindi eseguendo la tua regex match
Netherdan,

34

Ho scelto di scrivere questo invece di rimuovere manualmente il resto con le stringhe, quindi non devo affrontare i problemi di matematica che derivano dai numeri:

num = num.toString(); //If it's not already a String
num = num.slice(0, (num.indexOf("."))+3); //With 3 exposing the hundredths place
Number(num); //If you need it back as a Number

Questo ti darà "15.77" con num = 15.7784514;


5
Se non stai forzando un decimale, potresti voler aggiungere un condizionale nel caso in cui incontri numeri interi. In questo modo: num = num.toString (); if (num.indexOf (".")> 0) {num = num.slice (0, (num.indexOf (".")) + 3)}; Number (num);
ベ ン ノ ス ケ l'

1
bello se ha decimali ma se è un numero intero fallirà
Ruslan López

Se il numero è 0.00000052, allora sarà sbagliato ottenere 5.2e
Vasanth

1
@Vasanth Se il numero è 0,00000052 restituisce "0,00". Forse la risposta è stata modificata dal
Drenai il

Sì, fallisce nei casi limite
VPaul,

18

Ottobre 2017

Soluzione generale per troncare (senza arrotondare) un numero all'ennesima cifra decimale e convertirlo in una stringa con esattamente n cifre decimali, per qualsiasi n≥0.

function toFixedTrunc(x, n) {
  const v = (typeof x === 'string' ? x : x.toString()).split('.');
  if (n <= 0) return v[0];
  let f = v[1] || '';
  if (f.length > n) return `${v[0]}.${f.substr(0,n)}`;
  while (f.length < n) f += '0';
  return `${v[0]}.${f}`
}

dove x può essere un numero (che viene convertito in una stringa) o una stringa.

Ecco alcuni test per n = 2 (incluso quello richiesto da OP):

0           => 0.00
0.01        => 0.01
0.5839      => 0.58
0.999       => 0.99
1.01        => 1.01
2           => 2.00
2.551       => 2.55
2.99999     => 2.99
4.27        => 4.27
15.7784514  => 15.77
123.5999    => 123.59
0.000000199 => 1.99 *

* Come menzionato nella nota, ciò è dovuto alla conversione implicita javascript in esponenziale per "1.99e-7" E per alcuni altri valori di n:

15.001097   => 15.0010 (n=4)
0.000003298 => 0.0000032 (n=7)
0.000003298257899 => 0.000003298257 (n=12)

2
toFixedTrunc(0.000000199, 2) // 1.99
Maharramoff,

1
@ShamkhalMaharramov: se apri la console di sviluppo e inserisci 0.000000199 cosa ottieni? Ottieni 1,99e-7. Inoltre, se inserisci 0,000000199.toString () che cosa ottieni? Ottieni "1.99e-7" Quindi, quando passi 0.000000199 alla funzione, finisce per funzionare su "1.99e-7" non "0.000000199" e "correttamente" restituisce "1.99". Vedere ecma-international.org/ecma-262/6.0/...
SC1000

13

parseInt è più veloce di Math.floor

function floorFigure(figure, decimals){
    if (!decimals) decimals = 2;
    var d = Math.pow(10,decimals);
    return (parseInt(figure*d)/d).toFixed(decimals);
};

floorFigure(123.5999)    =>   "123.59"
floorFigure(123.5999, 3) =>   "123.599"

2
fallisce con 1234567,89
Ruslan López l'

Potresti elaborare Lopez?
zardilior,

3
floorFigure (4.56, 2) = 4.55
cryss

7
num = 19.66752
f = num.toFixed(3).slice(0,-1)
alert(f)

Questo restituirà 19.66


5
(4.9999) .toFixed (3) .slice (0, -1) restituisce 5,00, il risultato atteso è 4,99.
Bruno Lemos,

1
Consiglio invece di usare qualcosa come .toFixed (6) .slice (0, -4).
Bruno Lemos,

è perfetto, nel mio caso si sveglia ok. per esempio se voglio avere solo un numero decimale usare num.toFixed (2) .slice (0, -1) (se num ha 1.2356, restituirà 1.2)
Esteban Perez


5

Queste soluzioni funzionano, ma a me sembrano inutilmente complicate. Personalmente mi piace usare l'operatore del modulo per ottenere il resto di un'operazione di divisione e rimuoverlo. Supponendo che num = 15.7784514:

num-=num%.01;

Ciò equivale a dire num = num - (num% .01).


È interessante Nijkokun, grazie per averlo sottolineato. Non ho mai avuto problemi con questa tecnica, ma chiaramente dovrei dare un'occhiata più da vicino a casi come questo. In alternativa puoi usare ((num * = 100) - (num% 1)) / 100 per risolvere questo problema. La priorità nel mio caso è la velocità di esecuzione a causa del volume di calcoli a cui sto applicando questo, e questo è il modo più veloce per raggiungere questo obiettivo che ho trovato.
jtrick,

1
Il punto era evitare le ricerche e le conversioni di oggetti e funzioni richieste nelle altre soluzioni offerte. Grazie per il feedback!
jtrick,

1
fallisce anche con negativi come -5
Ruslan López,

Sono anche interessato a un arrotondamento rapido, come faresti che questo codice esegua 1 decimale?
thednp

5

Le risposte qui non mi hanno aiutato, hanno continuato ad arrotondare o a darmi il decimale sbagliato.

la mia soluzione converte il tuo decimale in una stringa, estrae i caratteri e quindi restituisce il tutto come un numero.

function Dec2(num) {
  num = String(num);
  if(num.indexOf('.') !== -1) {
    var numarr = num.split(".");
    if (numarr.length == 1) {
      return Number(num);
    }
    else {
      return Number(numarr[0]+"."+numarr[1].charAt(0)+numarr[1].charAt(1));
    }
  }
  else {
    return Number(num);
  }  
}

Dec2(99); // 99
Dec2(99.9999999); // 99.99
Dec2(99.35154); // 99.35
Dec2(99.8); // 99.8
Dec2(10265.985475); // 10265.98

Il 2 dicembre (99) dovrebbe restituire 99,00
VPaul

5

La mia versione per numeri positivi:

function toFixed_norounding(n,p)
{
    var result = n.toFixed(p);
    return result <= n ? result: (result - Math.pow(0.1,p)).toFixed(p);
}

Veloce, carino, ovvio. (versione per numeri positivi)


era necessario un arrotondamento per i valori float (ad es. denaro), con solo 1 decimale. La funzione sopra dovrebbe essere la "risposta" di questo argomento, è eccellente, funziona come un fascino. saluti all'autore e grazie. :)))
Adrian Tanase

Non riuscito per valore negativo. -0.7752. Il test toFixed_norounding(-0.7752,2)restituisce -0.78invece di-0.77
Ling Loeng il

4

Il seguente codice funziona molto bene per me:

num.toString().match(/.\*\\..{0,2}|.\*/)[0];

Aggiungerò il segno meno opzionale per renderlo perfetto -?;)
Ruslan López

3

Ho risolto usando il seguente modo semplice-

var num = 15.7784514;
Math.floor(num*100)/100;

I risultati saranno 15,77


Non funziona con valori negativi: -15.7784514restituisce-15.78
Clément Baconnier il

3

Basta troncare le cifre:

function truncDigits(inputNumber, digits) {
  const fact = 10 ** digits;
  return Math.floor(inputNumber * fact) / fact;
}

3

Un'altra soluzione a linea singola:

number = Math.trunc(number*100)/100

Ho usato 100 perché vuoi troncare alla seconda cifra, ma una soluzione più flessibile sarebbe:

number = Math.trunc(number*Math.pow(10, digits))/Math.pow(10, digits)

dove cifre è la quantità di cifre decimali da conservare.

Consulta le specifiche di Math.trunc per i dettagli e la compatibilità del browser.


1
Questa è la risposta migliore se non devi supportare IE11.
TJ.

2

Ecco qui. Una risposta che mostra ancora un altro modo per risolvere il problema:

// For the sake of simplicity, here is a complete function:
function truncate(numToBeTruncated, numOfDecimals) {
    var theNumber = numToBeTruncated.toString();
    var pointIndex = theNumber.indexOf('.');
    return +(theNumber.slice(0, pointIndex > -1 ? ++numOfDecimals + pointIndex : undefined));
}

Nota l'uso di + prima dell'espressione finale. Cioè per riconvertire la nostra stringa troncata e tranciata in tipo numerico.

Spero che sia d'aiuto!


1
Mi piace la semplicità di questo approccio e ritengo che tutte le soluzioni che evitano l'uso della matematica siano più appropriate per risolvere questo problema. Quindi, l'uso di slice () ecc. È la strada giusta da seguire. L'unico vantaggio del mio metodo è che elaborerà i numeri passati che sono stringhe [racchiuse tra virgolette [singole / doppie]]. Per qualche motivo, la funzione sopra ha generato un errore in FF, quando l'ho fatto: console.log ('truncate ("0.85156", 2)', truncate ("0.85156", 2));
Charles Robertson,

2

troncare senza zero

function toTrunc(value,n){  
    return Math.floor(value*Math.pow(10,n))/(Math.pow(10,n));
}

o

function toTrunc(value,n){
    x=(value.toString()+".0").split(".");
    return parseFloat(x[0]+"."+x[1].substr(0,n));
}

test:

toTrunc(17.4532,2)  //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1)   //1.4
toTrunc(.4,2)       //0.4

troncare con zero

function toTruncFixed(value,n){
    return toTrunc(value,n).toFixed(n);
}

test:

toTrunc(17.4532,2)  //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1)   //1.4
toTrunc(.4,2)       //0.40

2

Questo ha funzionato bene per me. Spero che risolverà anche i tuoi problemi.

function toFixedNumber(number) {
    const spitedValues = String(number.toLocaleString()).split('.');
    let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
    decimalValue = decimalValue.concat('00').substr(0,2);

    return '$'+spitedValues[0] + '.' + decimalValue;
}

// 5.56789      ---->  $5.56
// 0.342        ---->  $0.34
// -10.3484534  ---->  $-10.34 
// 600          ---->  $600.00

function convertNumber(){
  var result = toFixedNumber(document.getElementById("valueText").value);
  document.getElementById("resultText").value = result;
}


function toFixedNumber(number) {
        const spitedValues = String(number.toLocaleString()).split('.');
        let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
        decimalValue = decimalValue.concat('00').substr(0,2);

        return '$'+spitedValues[0] + '.' + decimalValue;
}
<div>
  <input type="text" id="valueText" placeholder="Input value here..">
  <br>
  <button onclick="convertNumber()" >Convert</button>
  <br><hr>
  <input type="text" id="resultText" placeholder="result" readonly="true">
</div>


2

Un modo semplice per farlo è il prossimo ma è necessario assicurarsi che il parametro quantità sia indicato come stringa.

function truncate(amountAsString, decimals = 2){
  var dotIndex = amountAsString.indexOf('.');
  var toTruncate = dotIndex !== -1  && ( amountAsString.length > dotIndex + decimals + 1);
  var approach = Math.pow(10, decimals);
  var amountToTruncate = toTruncate ? amountAsString.slice(0, dotIndex + decimals +1) : amountAsString;  
  return toTruncate
    ?  Math.floor(parseFloat(amountToTruncate) * approach ) / approach
    :  parseFloat(amountAsString);

}

console.log(truncate("7.99999")); //OUTPUT ==> 7.99
console.log(truncate("7.99999", 3)); //OUTPUT ==> 7.999
console.log(truncate("12.799999999999999")); //OUTPUT ==> 7.99

2

function formatLimitDecimals(value, decimals) {
  value = value.toString().split('.')

  if (value.length === 2) {
    return Number([value[0], value[1].slice(0, decimals)].join('.'))
  } else {
    return Number(value[0]);
  }
}

console.log(formatLimitDecimals(4.156, 2)); // 4.15
console.log(formatLimitDecimals(4.156, 8)); // 4.156
console.log(formatLimitDecimals(4.156, 0)); // 4


1

Ero abituato (num-0.05).toFixed(1)a ottenere il secondo decimale.


1

La mia soluzione in dattiloscritto (può essere facilmente trasferita su JS):

/**
 * Returns the price with correct precision as a string
 *
 * @param   price The price in decimal to be formatted.
 * @param   decimalPlaces The number of decimal places to use
 * @return  string The price in Decimal formatting.
 */
type toDecimal = (price: number, decimalPlaces?: number) => string;
const toDecimalOdds: toDecimal = (
  price: number,
  decimalPlaces: number = 2,
): string => {
  const priceString: string = price.toString();
  const pointIndex: number = priceString.indexOf('.');

  // Return the integer part if decimalPlaces is 0
  if (decimalPlaces === 0) {
    return priceString.substr(0, pointIndex);
  }

  // Return value with 0s appended after decimal if the price is an integer
  if (pointIndex === -1) {
    const padZeroString: string = '0'.repeat(decimalPlaces);

    return `${priceString}.${padZeroString}`;
  }

  // If numbers after decimal are less than decimalPlaces, append with 0s
  const padZeroLen: number = priceString.length - pointIndex - 1;
  if (padZeroLen > 0 && padZeroLen < decimalPlaces) {
    const padZeroString: string = '0'.repeat(padZeroLen);

    return `${priceString}${padZeroString}`;
  }

  return priceString.substr(0, pointIndex + decimalPlaces + 1);
};

Casi test:

  expect(filters.toDecimalOdds(3.14159)).toBe('3.14');
  expect(filters.toDecimalOdds(3.14159, 2)).toBe('3.14');
  expect(filters.toDecimalOdds(3.14159, 0)).toBe('3');
  expect(filters.toDecimalOdds(3.14159, 10)).toBe('3.1415900000');
  expect(filters.toDecimalOdds(8.2)).toBe('8.20');

Qualche miglioramento?


0

Ruota la tua toFixedfunzione: per valori positivi Math.floorfunziona bene.

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}

Per i valori negativi Math.floorè il giro dei valori. Quindi puoi usare Math.ceilinvece.

Esempio,

Math.ceil(-15.778665 * 10000) / 10000 = -15.7786
Math.floor(-15.778665 * 10000) / 10000 = -15.7787 // wrong.

5
Molte di queste risposte hanno una moltiplicazione all'interno di una funzione Math.floor (). Questo fallirà per alcuni numeri! L'aritmetica in virgola mobile non è precisa ed è necessario utilizzare metodi diversi.
Nico Westerdale,

0

La seconda soluzione di Gumbo, con l'espressione regolare, funziona ma è lenta a causa dell'espressione regolare. La prima soluzione di Gumbo fallisce in determinate situazioni a causa dell'imprecisione nei numeri in virgola mobile. Vedi il JSFiddle per una dimostrazione e un punto di riferimento. La seconda soluzione richiede circa 1636 nanosecondi per chiamata sul mio sistema attuale, CPU Intel Core i5-2500 a 3,30 GHz.

La soluzione che ho scritto prevede l'aggiunta di una piccola compensazione per occuparsi dell'imprecisione in virgola mobile. È sostanzialmente istantaneo, cioè sull'ordine dei nanosecondi. Ho registrato 2 nanosecondi per chiamata ma i timer JavaScript non sono molto precisi o granulari. Ecco il JS Fiddle e il codice.

function toFixedWithoutRounding (value, precision)
{
    var factorError = Math.pow(10, 14);
    var factorTruncate = Math.pow(10, 14 - precision);
    var factorDecimal = Math.pow(10, precision);
    return Math.floor(Math.floor(value * factorError + 1) / factorTruncate) / factorDecimal;
}

var values = [1.1299999999, 1.13, 1.139999999, 1.14, 1.14000000001, 1.13 * 100];

for (var i = 0; i < values.length; i++)
{
    var value = values[i];
    console.log(value + " --> " + toFixedWithoutRounding(value, 2));
}

for (var i = 0; i < values.length; i++)
{
    var value = values[i];
    console.log(value + " --> " + toFixedWithoutRounding(value, 4));
}

console.log("type of result is " + typeof toFixedWithoutRounding(1.13 * 100 / 100, 2));

// Benchmark
var value = 1.13 * 100;
var startTime = new Date();
var numRun = 1000000;
var nanosecondsPerMilliseconds = 1000000;

for (var run = 0; run < numRun; run++)
    toFixedWithoutRounding(value, 2);

var endTime = new Date();
var timeDiffNs = nanosecondsPerMilliseconds * (endTime - startTime);
var timePerCallNs = timeDiffNs / numRun;
console.log("Time per call (nanoseconds): " + timePerCallNs);

0

Sulla base della risposta di David D :

function NumberFormat(num,n) {
  var num = (arguments[0] != null) ? arguments[0] : 0;
  var n = (arguments[1] != null) ? arguments[1] : 2;
  if(num > 0){
    num = String(num);
    if(num.indexOf('.') !== -1) {
      var numarr = num.split(".");
      if (numarr.length > 1) {
        if(n > 0){
          var temp = numarr[0] + ".";
          for(var i = 0; i < n; i++){
            if(i < numarr[1].length){
              temp += numarr[1].charAt(i);
            }
          }
          num = Number(temp);
        }
      }
    }
  }
  return Number(num);
}

console.log('NumberFormat(123.85,2)',NumberFormat(123.85,2));
console.log('NumberFormat(123.851,2)',NumberFormat(123.851,2));
console.log('NumberFormat(0.85,2)',NumberFormat(0.85,2));
console.log('NumberFormat(0.851,2)',NumberFormat(0.851,2));
console.log('NumberFormat(0.85156,2)',NumberFormat(0.85156,2));
console.log('NumberFormat(0.85156,4)',NumberFormat(0.85156,4));
console.log('NumberFormat(0.85156,8)',NumberFormat(0.85156,8));
console.log('NumberFormat(".85156",2)',NumberFormat(".85156",2));
console.log('NumberFormat("0.85156",2)',NumberFormat("0.85156",2));
console.log('NumberFormat("1005.85156",2)',NumberFormat("1005.85156",2));
console.log('NumberFormat("0",2)',NumberFormat("0",2));
console.log('NumberFormat("",2)',NumberFormat("",2));
console.log('NumberFormat(85156,8)',NumberFormat(85156,8));
console.log('NumberFormat("85156",2)',NumberFormat("85156",2));
console.log('NumberFormat("85156.",2)',NumberFormat("85156.",2));

// NumberFormat(123.85,2) 123.85
// NumberFormat(123.851,2) 123.85
// NumberFormat(0.85,2) 0.85
// NumberFormat(0.851,2) 0.85
// NumberFormat(0.85156,2) 0.85
// NumberFormat(0.85156,4) 0.8515
// NumberFormat(0.85156,8) 0.85156
// NumberFormat(".85156",2) 0.85
// NumberFormat("0.85156",2) 0.85
// NumberFormat("1005.85156",2) 1005.85
// NumberFormat("0",2) 0
// NumberFormat("",2) 0
// NumberFormat(85156,8) 85156
// NumberFormat("85156",2) 85156
// NumberFormat("85156.",2) 85156

0

È più affidabile ottenere due punti fluttuanti senza arrotondamento.

Risposta di riferimento

var number = 10.5859;
var fixed2FloatPoints = parseInt(number * 100) / 100;
console.log(fixed2FloatPoints);

Grazie !


0

Esistono già alcune risposte adeguate con espressione regolare e calcolo aritmetico, puoi anche provare questo

function myFunction() {
    var str = 12.234556; 
    str = str.toString().split('.');
    var res = str[1].slice(0, 2);
    document.getElementById("demo").innerHTML = str[0]+'.'+res;
}

// output: 12.23

0

Ecco cosa è stato fatto con la stringa

export function withoutRange(number) {
  const str = String(number);
  const dotPosition = str.indexOf('.');
  if (dotPosition > 0) {
    const length = str.substring().length;
    const end = length > 3 ? 3 : length;
    return str.substring(0, dotPosition + end);
  }
  return str;
}

0

Tutte queste risposte sembrano un po 'complicate. Vorrei solo sottrarre 0,5 dal tuo numero e utilizzare toFixed ().


Intendevi 0.005?
Luan Nguyen,

0

La soluzione più efficiente (per 2 cifre di frazione) è sottrarre 0,005 prima di chiamare toFixed()

function toFixed2( num ) { return (num-0.005).toFixed(2) }

Anche i numeri negativi verranno arrotondati per difetto (lontano da zero). L'OP non ha parlato di numeri negativi.


0

So che ci sono già alcuni esempi funzionanti, ma penso che valga la pena proporre il mio equivalente String.toFixed, alcuni potrebbero trovarlo utile.

Questa è la mia alternativa risolta, che non arrotonda i numeri, semplicemente li tronca o aggiunge zero in base alla precisione data. Per un numero extra lungo utilizza l'arrotondamento incorporato JS quando la precisione è troppo lunga. La funzione funziona per tutti i numeri problematici che ho trovato nello stack.

function toFixedFixed(value, precision = 0) {
    let stringValue = isNaN(+value) ? '0' : String(+value);

    if (stringValue.indexOf('e') > -1 || stringValue === 'Infinity' || stringValue === '-Infinity') {
        throw new Error('To large number to be processed');
    }

    let [ beforePoint, afterPoint ] = stringValue.indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];

    // Force automatic rounding for some long real numbers that ends with 99X, by converting it to string, cutting off last digit, then adding extra nines and casting it on number again
    // e.g. 2.0199999999999996: +('2.019999999999999' + '9999') will give 2.02
    if (stringValue.length >= 17 && afterPoint.length > 2 && +afterPoint.substr(afterPoint.length - 3) > 995) {
        stringValue = String(+(stringValue.substr(0, afterPoint.length - 1) + '9'.repeat(stringValue.split('.').shift().length + 4)));
        [ beforePoint, afterPoint ] = String(stringValue).indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];
    }

    if (precision === 0) {
        return beforePoint;
    } else if (afterPoint.length > precision) {
        return `${beforePoint}.${afterPoint.substr(0, precision)}`;
    } else {
        return `${beforePoint}.${afterPoint}${'0'.repeat(precision - afterPoint.length)}`;
    }
}

Tieni presente che la precisione potrebbe non essere gestita correttamente per numeri di lunghezza 18 e superiori, ad esempio Chrome a 64 bit lo arrotonderà o aggiungerà "e +" / "e-" per mantenere la lunghezza del numero a 18.

Se si desidera eseguire operazioni su numeri reali, è più sicuro moltiplicarlo per Math.sqrt(10, precision)primo, eseguire i calcoli, quindi immergere il risultato per il valore del moltiplicatore.

Esempio:

0.06 + 0.01è 0.06999999999999999, e ogni funzione di formattazione che non è arrotondata la troncerà 0.06per precisione 2.

Ma se eseguirai la stessa operazione con moltiplicatore e divisore (0.06 * 100 + 0.01 * 100) / 100:, otterrai 0.07.

Ecco perché è così importante utilizzare tale moltiplicatore / divisore quando si ha a che fare con numeri reali in JavaScript, soprattutto quando si calcola il denaro ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.