Jak uniknąć notacji naukowej dla dużych liczb w JavaScript?


183

JavaScript przekształca dużą INT w notację naukową, gdy liczba staje się duża. Jak mogę temu zapobiec?


1
Czy chcesz, aby 1E21 wyświetlał się jako „1000000000000000000000”? Czy martwi Cię sposób wyświetlania numeru lub sposób jego przechowywania?
— poza

3
martwię się, jak to jest wyświetlane: Mam polecenie document.write (moja zmienna)
— Chris

1
Potrzebuję tego numeru jako części adresu URL
— Chris

3
@outis: Użytkownicy nie są jedynymi, którzy chcą czytać liczby. Wygląda na to, że D3 zgłosi wyjątek, gdy napotka translatetransformację zawierającą współrzędne w notacji naukowej.
— LUB Mapper

2
Nadal ma to zastosowanie w przypadku liczb do pewnego rozmiaru. Notacja naukowa będzie trudna do odczytania dla użytkowników, którzy mimo wszystko nie znają notacji naukowej.
— hippietrail

Odpowiedzi:


110

Istnieje Number.toFixed , ale używa notacji naukowej, jeśli liczba wynosi> = 1e21 i ma maksymalną precyzję 20. Poza tym możesz rzucić własną, ale będzie bałagan.

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

Powyżej używa taniego „łatwego” powtórzenia łańcucha ( (new Array(n+1)).join(str)). Możesz zdefiniowaćString.prototype.repeat za pomocą rosyjskiego mnożenia chłopów i użyć tego zamiast tego.

Ta odpowiedź powinna być stosowana tylko w kontekście pytania: wyświetlenie dużej liczby bez użycia notacji naukowej. Do wszystkiego innego należy użyć biblioteki BigInt , takiej jak BigNumber , Leemon's BigInt lub BigInteger . Idąc dalej, nowa natywna BigInt (uwaga: nie Leemona) powinna być dostępna; Chrom i oparte na nim przeglądarki ( Chrome , nowy Edge [v79 +], Brave ) i Firefox mają wsparcie; Wsparcie Safari jest w toku.

Oto jak użyjesz do tego BigInt: BigInt(n).toString()

Przykład:

Uważaj jednak, że każda liczba całkowita, którą wyprowadzasz jako kod JavaScript (nie BigInt), który ma więcej niż 15-16 cyfr (a konkretnie więcej niż Number.MAX_SAFE_INTEGER + 1[9 007 199, 254, 64, 94, 992]) może być zaokrąglona, ​​ponieważ typ liczby JavaScript (podwójna precyzja IEEE-754 zmiennoprzecinkowy) nie może dokładnie trzymać wszystkich liczb całkowitych poza tym punktem. Ponieważ Number.MAX_SAFE_INTEGER + 1działa w wielokrotnościach 2, więc nie może już przechowywać liczb nieparzystych (i podobnie, przy 18,014,398,508,489,481,984 zaczyna działać w wielokrotnościach 4, a następnie 8, a następnie 16, ...).

W związku z tym, jeśli możesz polegać na BigIntwsparciu, wypisz swój numer jako ciąg znaków przekazywany do BigIntfunkcji:

const n = BigInt("YourNumberHere");

Przykład:


Twoje rozwiązanie daje mi zupełnie inny wynik dla 2 ^ 1000 niż wolframalpha. Jakieś wskazówki?
— Shane Reustle,

4
@Shane: Pytania i odpowiedzi dotyczą wyświetlania liczb zmiennoprzecinkowych jako liczb całkowitych typu base-10 i nie dotyczą liczb, które nie mogą być reprezentowane w formacie liczb zmiennoprzecinkowych (które pojawią się podczas konwersji do podstawy 10). Potrzebujesz biblioteki bigint JS , jak wspomniano w ostatnim wierszu.
— outis

1
@PeterOlson: wygląda na to, że pominąłem Math.abs. Dzięki za zgłoszenie się.
— poza

1
toFixed(Number.MAX_VALUE) == Number.MAX_VALUEpowinien więc zwrócić prawdę, ale nie ...
— manonthemat

3
W rzeczywistości ten kod, jak jest, nie działa dla bardzo małych liczb ujemnych: toFixed (-1E-20) -> „0,0000000000000000000.09999999999999999”
— davidthings

44

Wiem, że to starsze pytanie, ale pokazuje ostatnio aktywne. 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"

możesz użyć opcji, aby sformatować dane wyjściowe.

Uwaga:

Number.toLocaleString () zaokrągla po 16 miejscach dziesiętnych, dzięki czemu ...

const myNumb = 586084736227728377283728272309128120398;
console.log( myNumb.toLocaleString('fullwide', { useGrouping: false }) );

...zwroty...

586084736227728400000000000000000000000

Jest to być może niepożądane, jeśli dokładność jest ważna w zamierzonym wyniku.


2
To jest niezawodna odpowiedź.
— Aria

To nie działa w PhantomJS 2.1.1 - wciąż trafia do notacji naukowej. Dobrze w Chrome.
— Egor Nepomnyaschih

1
Nie wydaje się to działać w przypadku bardzo małych miejsc po przecinku: var myNumb = 0,0000000001; console.log (myNumb.toLocaleString („fullwide”, {useGrouping: false}));
— eh1160,

Można ustawić opcję maximumSinentantDigits (maks. 21), aby formatować bardzo małe miejsca po przecinku, tj .:js console.log( myNumb.toLocaleString('fullwide', { useGrouping: true, maximumSignificantDigits:6}) );
— Sir. MaNiAl

20

W przypadku małej liczby i wiesz, ile liczb dziesiętnych chcesz, możesz użyć toFixed, a następnie użyć wyrażenia regularnego, aby usunąć końcowe zera.

Number(1e-7).toFixed(8).replace(/\.?0+$/,"") //0.000

26
pytanie dosłownie zadane dla dużej liczby
— swyx

1
Uważaj, aby uniknąć 0 jako argumentu połączenia toFixed - spowoduje to usunięcie znaczących zer końcowych:(1000).toFixed(0).replace(/\.?0+$/,"") // 1, not 1000
— Egor Nepomnyaschih

15

jeszcze jedno możliwe rozwiązanie:

function toFix(i){
 var str='';
 do{
   let a = i%10;
   i=Math.trunc(i/10);
   str = a+str;
 }while(i>0)
 return str;
}

7
To nie zachowuje oryginalnej wartości ... na przykład 31415926535897932384626433832795 staje się 31415926535897938480804068462624
— zero_cool

Nie pozytywne, ale prawdopodobnie związane z tym, jak JavaScript obsługuje duże liczby.
— zero_cool

@domsson Zasadniczo, ponieważ stosuje się arytmetykę liczb zmiennoprzecinkowych IEEE. liczby w JavaScript są w rzeczywistości reprezentowane jako liczba zmiennoprzecinkowa, a także „liczby dziesiętne”, nie ma natywnego „typu dokładnego liczby całkowitej”. Możesz przeczytać więcej tutaj: medium.com/dailyjs/javascripts-number-type-8d59199db1b6
— Pac0

@zero_cool Dowolna liczba większa niż Number.MAX_SAFE_INTEGERjest prawdopodobne, że ten problem wystąpi .
— Pac0

10

Oto mój krótki wariant Number.prototype.toFixedmetody, który działa z dowolną liczbą:

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"


jeśli porównasz Number.MAX_VALUE.toFixedSpecial (2) z Number.MAX_VALUE, zobaczysz, że nie są one równe.
— manonthemat

4
@manonthemat Oczywiście nie są one równe, ponieważ pierwszy to sformatowany ciąg, a drugi to Number. Jeśli rzucisz pierwszy na a Number, zobaczysz, że są absolutnie równe: jsfiddle.net/qd6hpnyx/1 . Możesz wycofać swój głos z powrotem:P
— VisioN

uczciwie .... Właśnie zauważyłem, że nie mogę, chyba że edytujesz swoją odpowiedź.
— manonthemat

Lepiej też zastąpić każdy końcowy .0pusty ciąg.
— vsync

Kiedy próbuję, dostaję nieco dziwną wartość console.log(2.2e307.toFixedSpecial(10)). Mam na myśli ... Dostaję kilka zer końcowych. I tak głosowanie, ponieważ wydaje się najbliższe temu, czego potrzebuję.
— peter.petrov

6

Poniższe rozwiązanie omija automatyczne formatowanie wykładnicze dla bardzo dużych i bardzo małych liczb. To rozwiązanie outisa z poprawką : nie działało dla bardzo małych liczb ujemnych.

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


1
numberToString (0,0000002) "0,00000019999999999999998"
— raphadko

1
@raphadko To znany problem precyzji zmiennoprzecinkowej Javascript , który jest kolejnym zupełnie innym problemem przy użyciu liczb w JS ... Zobacz na przykład stackoverflow.com/questions/1458633/…
— user56reinstatemonica8

3

Odpowiedzi innych osób nie podają dokładnej liczby!
Ta funkcja dokładnie oblicza żądaną liczbę i zwraca ją w ciągu, aby zapobiec jej zmianie przez javascript!
Jeśli potrzebujesz wyniku liczbowego, po prostu pomnóż wynik funkcji na pierwszym miejscu!

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

Przydałyby się dodatkowe informacje o odpowiedzi tylko na ten kod.
— Pyves,

Komentarze dodane do funkcji.

2

Wykorzystanie .toPrecision, .toFixeditd można policzyć liczbę cyfr w numerze konwertując go do łańcucha z .toStringpotem patrzy na jej .length.


z jakiegoś powodu toPrecision nie działa. jeśli spróbujesz: window.examplenum = 1352356324623461346, a następnie powiesz alert (window.examplenum.toPrecision (20)), nie pojawi się alert
— Chris

w rzeczywistości wyskakuje czasami z notacją naukową, a innym razem wcale nie wyskakuje. Co ja robię źle?
— Chris

18
Żadna z metod sugestii nie działa dla dużych (lub małych) liczb. (2e64).toString()wróci "2e+64", więc .lengthjest bezużyteczne.
— CodeManX,

2

Właśnie tego użyłem, aby pobrać wartość z danych wejściowych, zwiększając liczby mniejsze niż 17 cyfr i konwertując liczby wykładnicze na 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;
  }
}

1

Możesz zapętlić liczbę i uzyskać zaokrąglenie

// funkcjonalność zastępująca znak przy danym indeksie

String.prototype.replaceAt=function(index, character) {
    return this.substr(0, index) + character + this.substr(index+character.length);
}

// rozpoczyna się zapętlanie liczby

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

1

Próbowałem pracować z formą ciągu zamiast z liczbą i wydawało się, że to działa. Testowałem to tylko w Chrome, ale powinno być uniwersalne:

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

1

Myślę, że może być kilka podobnych odpowiedzi, ale oto coś, co wymyśliłem

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

Uwaga: jest to tak dokładne, jak funkcje matematyczne w javascript, i ma problemy przy użyciu log zamiast log10 w linii przed pętlą for; zapisze 1000 w bazie-10 jako 000, więc zmieniłem go na log10, ponieważ ludzie i tak będą w większości używać bazy-10.

To może nie być bardzo dokładne rozwiązanie, ale z dumą mogę powiedzieć, że może z powodzeniem tłumaczyć liczby między bazami i ma opcję przecinków!


1

Twoje pytanie:

number :0x68656c6c6f206f72656f
display:4.9299704811152646e+23

Możesz użyć tego: https://github.com/MikeMcl/bignumber.js

Biblioteka JavaScript do arytmetyki dziesiętnej i nie dziesiętnej o dowolnej precyzji.

lubię to:

let ten =new BigNumber('0x68656c6c6f206f72656f',16);
console.log(ten.toString(10));
display:492997048111526447310191

no cóż, strzeż się, że bignumber.js nie może wykraczać poza 15 cyfr znaczących ...
— Michael Heuberger

0

Wiem, że minęło wiele lat, ale ostatnio pracowałem nad podobnym problemem i chciałem opublikować swoje rozwiązanie. Akceptowana obecnie odpowiedź uzupełnia część wykładnikową zerami, a moja próbuje znaleźć dokładną odpowiedź, chociaż generalnie nie jest idealnie dokładna dla bardzo dużych liczb z powodu ograniczenia JS w precyzji zmiennoprzecinkowej.

To działa Math.pow(2, 100), zwracając poprawną wartość 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


@Oriol - tak, masz rację; Wydaje mi się, że z tym, co wcześniej wypróbowałem, po prostu tak się działało z powodu innych czynników. Usunę tę małą notatkę z mojej odpowiedzi.
— andi

1
nie działa:toFixed(Number.MAX_VALUE) == Number.MAX_VALUE
— manonthemat

0
function printInt(n) { return n.toPrecision(100).replace(/\..*/,""); }

z niektórymi problemami:

  • 0,9 jest wyświetlane jako „0”
  • -0,9 jest wyświetlane jako „-0”
  • 1e100 jest wyświetlany jako „1”
  • działa tylko dla liczb do ~ 1e99 => użyj innej stałej dla większych liczb; lub mniejszy do optymalizacji.

Tak, to niektóre problemy.
— Adam Leggett

0

Wyrzucanie wyrażeń regularnych. Nie ma to problemów z precyzją i nie zawiera dużo kodu.

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


-1

Jeśli robisz to tylko w celu wyświetlenia, możesz zbudować tablicę z cyfr, zanim zostaną zaokrąglone.

var num = Math.pow(2, 100);
var reconstruct = [];
while(num > 0) {
    reconstruct.unshift(num % 10);
    num = Math.floor(num / 10);
}
console.log(reconstruct.join(''));

To zwróci prawidłową odpowiedź, ale zajmie tyle czasu i może skończyć się upływem czasu wykonania.
— Hannah May

-1

Obecnie nie ma natywnej funkcji do rozwiązania notacji naukowej. Jednak w tym celu musisz napisać własną funkcjonalność.

Tutaj jest mój:

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

To się nie udaje w przypadku naprawdę dużych liczb. Próbowałem 2830869077153280552556547081187254342445169156730 i dostałem 2830869077153280500000000000000000000000000000000
— oddzwonienie

-1

Możesz użyć modułu wykładniczego . Jest lekki i w pełni przetestowany.

import fromExponential from 'from-exponential';

fromExponential(1.123e-10); // => '0.0000000001123'

-1

Możesz także użyć YourJS.fullNumber. Na przykładYourJS.fullNumber(Number.MAX_VALUE) powoduje, że: 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Działa również w przypadku naprawdę małych liczb. YourJS.fullNumber(Number.MIN_VALUE)zwraca to: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005

Należy zauważyć, że ta funkcja zawsze zwraca liczby skończone jako ciągi znaków, ale zwraca liczby nieskończone (np. NaNLub Infinity) jako undefined.

Możesz to przetestować w konsoli YourJS tutaj .


-3

Możesz użyć number.toString(10.1):

console.log(Number.MAX_VALUE.toString(10.1));

Uwaga: obecnie działa to w Chrome, ale nie w Firefox. Specyfikacja mówi, że podstawa musi być liczbą całkowitą, więc powoduje to niewiarygodne zachowanie.


co do cholery to robi? Podstawa 10,1?
— joniba

To nie działa Od wersji ES5 implementacje są wymagane do korzystania z argumentu ToInteger. Zatem używanie 10.1 lub 10nic nie jest równoważne.
— Oriol

Tak, to naprawdę przestało działać ostatnio. Trochę smutne, ale ta odpowiedź jest teraz nieistotna.
— Zambonifofex,

-6

Miałem ten sam problem z notacją naukową zwracającą wyrocznię, ale potrzebowałem rzeczywistej liczby dla adresu URL. Właśnie użyłem sztuczki PHP, odejmując zero i otrzymuję poprawną liczbę.

na przykład 5.4987E7 to val.

newval = val - 0;

newval wynosi teraz 54987000


2
To nie ma wpływu. 5.4987E7 ma wykładnik mniejszy niż 21, więc wyświetla się jako pełna liczba, niezależnie od tego, czy jest konwertowana na ciąg. (5.4987E21 - 0) .toString () => "5.4987e + 21"
— Dwight
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.