JavaScript dönüştüren büyük INT için bilimsel gösterimde sayı büyük olduğunda. Bunun olmasını nasıl önleyebilirim?
translate
Bilimsel gösterimde koordinatlar içeren bir dönüşümle karşılaşıldığında D3 bir istisna atacak gibi görünüyor .
JavaScript dönüştüren büyük INT için bilimsel gösterimde sayı büyük olduğunda. Bunun olmasını nasıl önleyebilirim?
translate
Bilimsel gösterimde koordinatlar içeren bir dönüşümle karşılaşıldığında D3 bir istisna atacak gibi görünüyor .
Yanıtlar:
Orada Number.toFixed , ama sayı> = 1e21 ve Bunun dışında 20 katlık bir maksimum hassaslık varsa o, kendi dönebilirsiniz bilimsel gösterim kullanır, ancak dağınık olacaktır.
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;
}
Yukarıdaki ucuz -nn-easy dize tekrarlama ( (new Array(n+1)).join(str)
) kullanır. TanımlayabilirsinizString.prototype.repeat
Rus Köylü Çarpmasını kullanarak ve bunun yerine kullanabilirsiniz.
Bu cevap sadece sorunun bağlamına uygulanmalıdır: bilimsel gösterim kullanmadan çok sayıda gösterim. Başka herhangi bir şey için, BigNumber , Leemon's BigInt veya BigInteger gibi bir BigInt kütüphanesi kullanmalısınız . Bundan sonra, yeni yerel BigInt (not: Leemon değil) mevcut olmalıdır; Chromium ve tarayıcılar ( Chrome , yeni Edge [v79 +], Brave ) ve Firefox'un hepsi destekliyor; Safari'nin desteği sürüyor.
Bunun için BigInt'i nasıl kullanacağınız aşağıda açıklanmıştır: BigInt(n).toString()
Misal:
Bununla birlikte, JavaScript numarası olarak (BigInt değil) çıkardığınız herhangi bir tam sayının Number.MAX_SAFE_INTEGER + 1
yuvarlanabileceğine dikkat edin (özellikle, [9,007,199,254,740,992] ' den büyük ) JavaScript'in sayı türü (IEEE-754 çift duyarlıklı) kayan nokta) tam olarak bu noktanın ötesindeki tam sayıları tutamaz. İtibariyle Number.MAX_SAFE_INTEGER + 1
artık tek sayılar tutamayacak yüzden, birçok 2 olarak çalışıyor (ve similiarly o zaman, o zaman, 4 katları 16 8 çalışmaya başlar 18,014,398,509,481,984 de, ...).
Sonuç olarak, BigInt
desteğe güvenebiliyorsanız, numaranızı BigInt
işleve ilettiğiniz bir dize olarak çıktılayın :
const n = BigInt("YourNumberHere");
Misal:
Math.abs
. Söylediğin için teşekkürler.
toFixed(Number.MAX_VALUE) == Number.MAX_VALUE
sonra doğru dönmelidir, ama değil ...
Bunun daha eski bir soru olduğunu biliyorum, ancak son zamanlarda aktif olduğunu gösteriyor. 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"
çıktıyı biçimlendirmek için seçenekleri kullanabilirsiniz.
Number.toLocaleString () 16 ondalık basamaktan sonra yuvarlar, böylece ...
const myNumb = 586084736227728377283728272309128120398;
console.log( myNumb.toLocaleString('fullwide', { useGrouping: false }) );
...İadeler...
586084736227728400000000000000000000000
Bu, sonuçta doğruluk önemliyse, belki de istenmeyen bir durumdur.
js console.log( myNumb.toLocaleString('fullwide', { useGrouping: true, maximumSignificantDigits:6}) );
Küçük sayı için ve kaç ondalık basamak istediğinizi bilirseniz, toFixed'i kullanabilir ve sonra da sıfırları kaldırmak için bir normal ifade kullanabilirsiniz.
Number(1e-7).toFixed(8).replace(/\.?0+$/,"") //0.000
(1000).toFixed(0).replace(/\.?0+$/,"") // 1, not 1000
bir olası çözüm daha:
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
Bu sorundan daha büyük olan herhangi bir sayı daha büyük olabilir .
İşte Number.prototype.toFixed
herhangi bir sayı ile çalışan kısa yöntem benim :
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
. Eğer bir ilk kişinin döküm ise Number
, olduklarını göreceksiniz kesinlikle : eşit jsfiddle.net/qd6hpnyx/1 . Downvote'unuzu geri alabilirsiniz:P
.0
boş dizeyle değiştirmek de daha iyidir .
console.log(2.2e307.toFixedSpecial(10))
. Demek istediğim ... Birkaç tane sıfır var. Yine de upvoting çünkü bu ihtiyacım olana en yakın görünüyor.
Aşağıdaki çözüm, çok büyük ve çok küçük sayılar için otomatik üslü biçimlendirmeyi atlar. Bu outis çözümü düzeltme yaptı şununla: Çok küçük negatif sayılar için çalışma değildi.
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));
Başkalarının cevapları size tam sayıyı vermez!
Bu işlev, istenen sayıyı doğru bir şekilde hesaplar ve javascript tarafından değiştirilmesini önlemek için dizeye döndürür!
Sayısal bir sonuca ihtiyacınız varsa, fonksiyonun sonucunu bir numarada çarpın!
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;
}
Kullanın .toPrecision
, .toFixed
vb. Kullanın . Sayınızdaki rakam sayısını bir dizgeye dönüştürüp .toString
sonra ona bakarak çevirebilirsiniz .length
.
(2e64).toString()
dönecektir "2e+64"
, bu .length
işe yaramaz.
Bu değeri bir girişten almak, 17 basamaktan küçük sayıları genişletmek ve Üstel sayıları x10 y'ye dönüştürmek için kullandım.
// 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;
}
}
Sayı üzerinde döngü ve yuvarlama elde edebilirsiniz
// verilen dizinde karakter değiştirme işlevi
String.prototype.replaceAt=function(index, character) {
return this.substr(0, index) + character + this.substr(index+character.length);
}
// sayı üzerinde döngü başlar
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--;
}
}
Numara yerine dize formu ile çalışmayı denedim ve bu işe yaramış gibiydi. Bunu yalnızca Chrome'da test ettim, ancak evrensel olmalı:
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;
}
Sanırım birkaç benzer cevap olabilir, ama işte bulduğum bir şey
// 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);
Not: Bu sadece javascript math işlevleri kadar doğrudur ve for döngüsünün önündeki satırda log10 yerine log kullanıldığında problemleri vardır; baz-10'a 1000 olarak 1000 yazacak, bu yüzden log10 olarak değiştirdim çünkü insanlar çoğunlukla baz-10'u kullanacaklar.
Bu çok doğru bir çözüm olmayabilir, ancak sayıları üsler arasında başarıyla çevirebildiğini ve virgül için bir seçenekle geldiğini söylemekten gurur duyuyorum!
Senin sorun:
number :0x68656c6c6f206f72656f
display:4.9299704811152646e+23
Bunu kullanabilirsiniz: https://github.com/MikeMcl/bignumber.js
Rasgele kesinlikli ondalık ve ondalık olmayan aritmetik için bir JavaScript kitaplığı.
bunun gibi:
let ten =new BigNumber('0x68656c6c6f206f72656f',16);
console.log(ten.toString(10));
display:492997048111526447310191
Yıllar sonra biliyorum, ama son zamanlarda benzer bir konu üzerinde çalışıyordum ve çözümümü göndermek istedim. Şu anda kabul edilen cevap, üssü kısmı 0'larla dolduruyor ve mayın kesin cevabı bulmaya çalışıyor, ancak JS'nin kayan nokta hassasiyetindeki limiti nedeniyle genel olarak çok büyük sayılar için mükemmel bir şekilde doğru değil.
Bu, Math.pow(2, 100)
1267650600228229401496703205376'nın doğru değerini döndürerek işe yarar.
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(/\..*/,""); }
bazı sorunlarla:
Düzenli ifadeleri patlatmak. Bunun hassas bir sorunu yoktur ve çok fazla kod değildir.
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));
Sadece görüntüleme için yapıyorsanız, yuvarlamadan önce rakamlardan bir dizi oluşturabilirsiniz.
var num = Math.pow(2, 100);
var reconstruct = [];
while(num > 0) {
reconstruct.unshift(num % 10);
num = Math.floor(num / 10);
}
console.log(reconstruct.join(''));
Şu anda bilimsel gösterimi çözecek yerel bir işlev bulunmamaktadır. Ancak, bu amaçla kendi işlevselliğinizi yazmalısınız.
İşte benim:
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("");
}
YourJS.fullNumber öğenizi de kullanabilirsiniz. Örneğin YourJS.fullNumber(Number.MAX_VALUE)
, aşağıdakilerle sonuçlanır:
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Aynı zamanda gerçekten küçük sayılar için de çalışır. YourJS.fullNumber(Number.MIN_VALUE)
bunu döndürür:
0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005
Bu işlevin her zaman sonlu sayıları dize olarak döndüreceğini ancak sonlu olmayan sayıları (örn. NaN
Veya Infinity
) olarak döndüreceğini unutmamak önemlidir undefined
.
Bunu YourJS Konsolunuzda test edebilirsiniz .
Şunları kullanabilirsiniz number.toString(10.1)
:
console.log(Number.MAX_VALUE.toString(10.1));
Not: Bu şu anda Chrome'da çalışıyor, ancak Firefox'ta çalışmıyor. Spesifikasyon, radix'in bir tamsayı olması gerektiğini söylüyor, bu da güvenilmez davranışla sonuçlanıyor.
10.1
ya 10
da hiçbir şey eşdeğer değildir.
Kahin geri dönen bilimsel gösterimle aynı sorunu yaşadım, ancak bir url için gerçek sayıya ihtiyacım vardı. Ben sadece sıfır çıkararak bir PHP hile kullandım ve doğru numarayı almak.
örneğin 5.4987E7 val'dir.
newval = val - 0;
newval artık 54987000'e eşit