JavaScript converte un grande INT in notazione scientifica quando il numero diventa grande. Come posso evitare che ciò accada?
translatetrasformazione che contiene coordinate in notazione scientifica.
JavaScript converte un grande INT in notazione scientifica quando il numero diventa grande. Come posso evitare che ciò accada?
translatetrasformazione che contiene coordinate in notazione scientifica.
Risposte:
C'è Number.toFixed , ma usa la notazione scientifica se il numero è> = 1e21 e ha una precisione massima di 20. A parte questo, puoi lanciare il tuo, ma sarà disordinato.
function toFixed(x) {
if (Math.abs(x) < 1.0) {
var e = parseInt(x.toString().split('e-')[1]);
if (e) {
x *= Math.pow(10,e-1);
x = '0.' + (new Array(e)).join('0') + x.toString().substring(2);
}
} else {
var e = parseInt(x.toString().split('+')[1]);
if (e > 20) {
e -= 20;
x /= Math.pow(10,e);
x += (new Array(e+1)).join('0');
}
}
return x;
}
Sopra usa la ripetizione di stringhe cheap-'n'-easy ( (new Array(n+1)).join(str)). Puoi definire String.prototype.repeatusando la moltiplicazione contadina russa e usarla invece.
Questa risposta dovrebbe essere applicata solo al contesto della domanda: visualizzare un numero elevato senza usare la notazione scientifica. Per ogni altra cosa, dovresti usare una libreria BigInt , come BigNumber , Leemon's BigInt o BigInteger . In futuro, dovrebbe essere disponibile il nuovo BigInt nativo (nota: non di Leemon); Chromium e browser basati su di esso ( Chrome , il nuovo Edge [v79 +], Brave ) e Firefox hanno tutti supporto; Il supporto di Safari è in corso.
Ecco come useresti BigInt per questo: BigInt(n).toString()
Esempio:
Fai attenzione , tuttavia, che qualsiasi numero intero che hai emesso come numero JavaScript (non come BigInt) che è più di 15-16 cifre (in particolare, maggiore di Number.MAX_SAFE_INTEGER + 1[9.007.199.254.740.992]) può essere arrotondato, perché il tipo di numero JavaScript (IEEE-754 doppia precisione virgola mobile) non può contenere con precisione tutti i numeri interi oltre quel punto. Al Number.MAX_SAFE_INTEGER + 1momento funziona in multipli di 2, quindi non può più contenere numeri dispari (e allo stesso modo, a 18.014.398.509.481.984 inizia a lavorare in multipli di 4, quindi 8, quindi 16, ...).
Di conseguenza, se puoi fare affidamento sul BigIntsupporto, emetti il tuo numero come una stringa che passi alla BigIntfunzione:
const n = BigInt("YourNumberHere");
Esempio:
Math.abs. Grazie per il testa a testa.
toFixed(Number.MAX_VALUE) == Number.MAX_VALUEdovrebbe tornare vero allora, ma non ...
So che questa è una domanda più vecchia, ma mostra di recente attiva. MDN toLocaleString
const myNumb = 1000000000000000000000;
console.log( myNumb ); // 1e+21
console.log( myNumb.toLocaleString() ); // "1,000,000,000,000,000,000,000"
console.log( myNumb.toLocaleString('fullwide', {useGrouping:false}) ); // "1000000000000000000000"
è possibile utilizzare le opzioni per formattare l'output.
Number.toLocaleString () arrotonda dopo 16 cifre decimali, in modo che ...
const myNumb = 586084736227728377283728272309128120398;
console.log( myNumb.toLocaleString('fullwide', { useGrouping: false }) );
...ritorna...
586084736227728400000000000000000000000
Ciò è forse indesiderabile se l'accuratezza è importante nel risultato previsto.
js console.log( myNumb.toLocaleString('fullwide', { useGrouping: true, maximumSignificantDigits:6}) );
Per un piccolo numero e sai quanti decimali vuoi, puoi usare Fisso e quindi usare una regexp per rimuovere gli zeri finali.
Number(1e-7).toFixed(8).replace(/\.?0+$/,"") //0.000
(1000).toFixed(0).replace(/\.?0+$/,"") // 1, not 1000
un'altra soluzione possibile:
function toFix(i){
var str='';
do{
let a = i%10;
i=Math.trunc(i/10);
str = a+str;
}while(i>0)
return str;
}
Number.MAX_SAFE_INTEGERè probabile che subisca questo problema.
Ecco la mia breve variante del Number.prototype.toFixedmetodo che funziona con qualsiasi numero:
Number.prototype.toFixedSpecial = function(n) {
var str = this.toFixed(n);
if (str.indexOf('e+') === -1)
return str;
// if number is in scientific notation, pick (b)ase and (p)ower
str = str.replace('.', '').split('e+').reduce(function(p, b) {
return p + Array(b - p.length + 2).join(0);
});
if (n > 0)
str += '.' + Array(n + 1).join(0);
return str;
};
console.log( 1e21.toFixedSpecial(2) ); // "1000000000000000000000.00"
console.log( 2.1e24.toFixedSpecial(0) ); // "2100000000000000000000000"
console.log( 1234567..toFixedSpecial(1) ); // "1234567.0"
console.log( 1234567.89.toFixedSpecial(3) ); // "1234567.890"
Number. Se lanci il primo in a Number, vedrai che sono assolutamente uguali: jsfiddle.net/qd6hpnyx/1 . Puoi riprendere il tuo :P
.0con stringa vuota.
console.log(2.2e307.toFixedSpecial(10)). Voglio dire ... ho diversi zeri finali. Voto comunque perché questo sembra più vicino a ciò di cui ho bisogno.
La seguente soluzione ignora la formattazione esponenziale automatica per numeri molto grandi e molto piccoli. Questa è la soluzione di Outis con un bugfix: non funzionava con numeri negativi molto piccoli.
function numberToString(num)
{
let numStr = String(num);
if (Math.abs(num) < 1.0)
{
let e = parseInt(num.toString().split('e-')[1]);
if (e)
{
let negative = num < 0;
if (negative) num *= -1
num *= Math.pow(10, e - 1);
numStr = '0.' + (new Array(e)).join('0') + num.toString().substring(2);
if (negative) numStr = "-" + numStr;
}
}
else
{
let e = parseInt(num.toString().split('+')[1]);
if (e > 20)
{
e -= 20;
num /= Math.pow(10, e);
numStr = num.toString() + (new Array(e + 1)).join('0');
}
}
return numStr;
}
// testing ...
console.log(numberToString(+0.0000000000000000001));
console.log(numberToString(-0.0000000000000000001));
console.log(numberToString(+314564649798762418795));
console.log(numberToString(-314564649798762418795));
Le risposte degli altri non ti danno il numero esatto!
Questa funzione calcola accuratamente il numero desiderato e lo restituisce nella stringa per impedirne la modifica tramite JavaScript!
Se hai bisogno di un risultato numerico, basta moltiplicare il risultato della funzione nel numero uno!
function toNonExponential(value) {
// if value is not a number try to convert it to number
if (typeof value !== "number") {
value = parseFloat(value);
// after convert, if value is not a number return empty string
if (isNaN(value)) {
return "";
}
}
var sign;
var e;
// if value is negative, save "-" in sign variable and calculate the absolute value
if (value < 0) {
sign = "-";
value = Math.abs(value);
}
else {
sign = "";
}
// if value is between 0 and 1
if (value < 1.0) {
// get e value
e = parseInt(value.toString().split('e-')[1]);
// if value is exponential convert it to non exponential
if (e) {
value *= Math.pow(10, e - 1);
value = '0.' + (new Array(e)).join('0') + value.toString().substring(2);
}
}
else {
// get e value
e = parseInt(value.toString().split('e+')[1]);
// if value is exponential convert it to non exponential
if (e) {
value /= Math.pow(10, e);
value += (new Array(e + 1)).join('0');
}
}
// if value has negative sign, add to it
return sign + value;
}
Usa .toPrecision, .toFixedecc. Puoi contare il numero di cifre nel tuo numero convertendolo in una stringa e .toStringosservandolo .length.
(2e64).toString()tornerà "2e+64", quindi .lengthè inutile.
Questo è quello che ho finito per prendere il valore da un input, espandendo i numeri a meno di 17 cifre e convertendo i numeri esponenziali in x10 y
// e.g.
// niceNumber("1.24e+4") becomes
// 1.24x10 to the power of 4 [displayed in Superscript]
function niceNumber(num) {
try{
var sOut = num.toString();
if ( sOut.length >=17 || sOut.indexOf("e") > 0){
sOut=parseFloat(num).toPrecision(5)+"";
sOut = sOut.replace("e","x10<sup>")+"</sup>";
}
return sOut;
}
catch ( e) {
return num;
}
}
Puoi scorrere il numero e ottenere l'arrotondamento
// funzionalità per sostituire il carattere in un determinato indice
String.prototype.replaceAt=function(index, character) {
return this.substr(0, index) + character + this.substr(index+character.length);
}
// inizia il ciclo sul numero
var str = "123456789123456799.55";
var arr = str.split('.');
str = arr[0];
i = (str.length-1);
if(arr[1].length && Math.round(arr[1]/100)){
while(i>0){
var intVal = parseInt(str.charAt(i));
if(intVal == 9){
str = str.replaceAt(i,'0');
console.log(1,str)
}else{
str = str.replaceAt(i,(intVal+1).toString());
console.log(2,i,(intVal+1).toString(),str)
break;
}
i--;
}
}
Ho provato a lavorare con il modulo stringa anziché con il numero e questo sembra funzionare. L'ho provato solo su Chrome ma dovrebbe essere universale:
function removeExponent(s) {
var ie = s.indexOf('e');
if (ie != -1) {
if (s.charAt(ie + 1) == '-') {
// negative exponent, prepend with .0s
var n = s.substr(ie + 2).match(/[0-9]+/);
s = s.substr(2, ie - 2); // remove the leading '0.' and exponent chars
for (var i = 0; i < n; i++) {
s = '0' + s;
}
s = '.' + s;
} else {
// positive exponent, postpend with 0s
var n = s.substr(ie + 1).match(/[0-9]+/);
s = s.substr(0, ie); // strip off exponent chars
for (var i = 0; i < n; i++) {
s += '0';
}
}
}
return s;
}
Penso che ci possano essere diverse risposte simili, ma ecco una cosa che mi è venuta in mente
// If you're gonna tell me not to use 'with' I understand, just,
// it has no other purpose, ;( andthe code actually looks neater
// 'with' it but I will edit the answer if anyone insists
var commas = false;
function digit(number1, index1, base1) {
with (Math) {
return floor(number1/pow(base1, index1))%base1;
}
}
function digits(number1, base1) {
with (Math) {
o = "";
l = floor(log10(number1)/log10(base1));
for (var index1 = 0; index1 < l+1; index1++) {
o = digit(number1, index1, base1) + o;
if (commas && i%3==2 && i<l) {
o = "," + o;
}
}
return o;
}
}
// Test - this is the limit of accurate digits I think
console.log(1234567890123450);
Nota: questo è accurato solo come le funzioni matematiche javascript e ha problemi quando si utilizza log anziché log10 sulla riga prima del ciclo for; scriverà 1000 in base-10 come 000, quindi l'ho cambiato in log10 perché le persone useranno principalmente la base-10 comunque.
Questa potrebbe non essere una soluzione molto accurata, ma sono orgoglioso di dire che può tradurre con successo i numeri attraverso le basi e viene fornito con un'opzione per le virgole!
La tua domanda:
number :0x68656c6c6f206f72656f
display:4.9299704811152646e+23
Puoi usare questo: https://github.com/MikeMcl/bignumber.js
Una libreria JavaScript per l'aritmetica decimale e non decimale di precisione arbitraria.
come questo:
let ten =new BigNumber('0x68656c6c6f206f72656f',16);
console.log(ten.toString(10));
display:492997048111526447310191
So che sono passati molti anni, ma di recente avevo lavorato su un problema simile e volevo pubblicare la mia soluzione. La risposta attualmente accettata completa la parte esponente con 0 e la mia tenta di trovare la risposta esatta, sebbene in generale non sia perfettamente accurata per numeri molto grandi a causa del limite di JS nella precisione in virgola mobile.
Questo funziona per Math.pow(2, 100), restituendo il valore corretto di 1267650600228229401496703205376.
function toFixed(x) {
var result = '';
var xStr = x.toString(10);
var digitCount = xStr.indexOf('e') === -1 ? xStr.length : (parseInt(xStr.substr(xStr.indexOf('e') + 1)) + 1);
for (var i = 1; i <= digitCount; i++) {
var mod = (x % Math.pow(10, i)).toString(10);
var exponent = (mod.indexOf('e') === -1) ? 0 : parseInt(mod.substr(mod.indexOf('e')+1));
if ((exponent === 0 && mod.length !== i) || (exponent > 0 && exponent !== i-1)) {
result = '0' + result;
}
else {
result = mod.charAt(0) + result;
}
}
return result;
}
console.log(toFixed(Math.pow(2,100))); // 1267650600228229401496703205376
toFixed(Number.MAX_VALUE) == Number.MAX_VALUE
function printInt(n) { return n.toPrecision(100).replace(/\..*/,""); }
con alcuni problemi:
Eliminare le espressioni regolari. Questo non ha problemi di precisione e non è un sacco di codice.
function toPlainString(num) {
return (''+num).replace(/(-?)(\d*)\.?(\d+)e([+-]\d+)/,
function(a,b,c,d,e) {
return e < 0
? b + '0.' + Array(1-e-c.length).join(0) + c + d
: b + c + d + Array(e-d.length+1).join(0);
});
}
console.log(toPlainString(12345e+12));
console.log(toPlainString(12345e+24));
console.log(toPlainString(-12345e+24));
console.log(toPlainString(12345e-12));
console.log(toPlainString(123e-12));
console.log(toPlainString(-123e-12));
console.log(toPlainString(-123.45e-56));
Se lo stai semplicemente facendo per la visualizzazione, puoi costruire un array dalle cifre prima che siano arrotondate.
var num = Math.pow(2, 100);
var reconstruct = [];
while(num > 0) {
reconstruct.unshift(num % 10);
num = Math.floor(num / 10);
}
console.log(reconstruct.join(''));
Attualmente non esiste una funzione nativa per dissolvere la notazione scientifica. Tuttavia, a tal fine è necessario scrivere le proprie funzionalità.
Ecco il mio:
function dissolveExponentialNotation(number)
{
if(!Number.isFinite(number)) { return undefined; }
let text = number.toString();
let items = text.split('e');
if(items.length == 1) { return text; }
let significandText = items[0];
let exponent = parseInt(items[1]);
let characters = Array.from(significandText);
let minus = characters[0] == '-';
if(minus) { characters.splice(0, 1); }
let indexDot = characters.reduce((accumulator, character, index) =>
{
if(!accumulator.found) { if(character == '.') { accumulator.found = true; } else { accumulator.index++; } }
return accumulator;
}, { index: 0, found: false }).index;
characters.splice(indexDot, 1);
indexDot += exponent;
if(indexDot >= 0 && indexDot < characters.length - 1)
{
characters.splice(indexDot, 0, '.');
}
else if(indexDot < 0)
{
characters.unshift("0.", "0".repeat(-indexDot));
}
else
{
characters.push("0".repeat(indexDot - characters.length));
}
return (minus ? "-" : "") + characters.join("");
}
È possibile utilizzare il modulo from-esponential . È leggero e completamente testato.
import fromExponential from 'from-exponential';
fromExponential(1.123e-10); // => '0.0000000001123'
Puoi anche usare YourJS.fullNumber. Ad esempio, si YourJS.fullNumber(Number.MAX_VALUE)ottiene quanto segue:
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Funziona anche con numeri molto piccoli. YourJS.fullNumber(Number.MIN_VALUE)restituisce questo:
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005
È importante notare che questa funzione restituirà sempre numeri finiti come stringhe ma restituirà numeri non finiti (ad es. NaNOppure Infinity) come undefined.
Puoi provarlo nella tua console YourJS qui .
Puoi usare number.toString(10.1):
console.log(Number.MAX_VALUE.toString(10.1));
Nota: attualmente funziona in Chrome, ma non in Firefox. La specifica dice che il radix deve essere un numero intero, quindi questo comporta un comportamento inaffidabile.
10.1 o 10o niente sono equivalenti.
Ho avuto lo stesso problema con l'oracolo che restituiva la notazione scientifica, ma avevo bisogno del numero effettivo per un url. Ho appena usato un trucco PHP sottraendo zero e ottengo il numero corretto.
per esempio 5.4987E7 è il val.
newval = val - 0;
newval ora equivale a 54987000