Jak stwierdził Quentin, jest to kwestia zmiennoprzecinkowa IEEE.
0.1
faktycznie nie istnieje w dziesiętnym zmiennoprzecinkowy technicznie po prostu ze względu na sposób działania binarnego.
0.1
jest jedna dziesiąta lub 1/10. Aby pokazać je w systemie binarnym, podzielić binarne 1 przez binarnego 1010, stosując podział binarny długo:
Jak widać, 0.1
binarnie jest 0.0001100110011....0011
i będzie powtarzać 0011
na koniec do nieskończoności.
Przeglądarki wybierają i wybierają najbliższy dostępny punkt do 0.1
i używają tego jako nieprzezroczystości. Niektórzy przejdą, a niektórzy przejdą.
FireFox zgaduję, że po prostu pokazuje wersję czytelną dla człowieka, ale w rzeczywistości jest to naprawdę użyteczny komputer zmiennoprzecinkowy.
Jako przykład:
body {
color: rgba(0,0,0,0.1); // actually 0.0980392
opacity: 0.1; // actually 0.100000001490116
}
Dwie zupełnie różne wartości dokładnie w tym samym punkcie pływających.
Ten problem zmiennoprzecinkowy może być zreplikowany w innych miejscach w przeglądarkach korzystających z innych języków, takich jak JavaScript. Numery JavaScript są zawsze 64-bitowym zmiennoprzecinkowym (co moim zdaniem jest również CSS). Jest to bardziej powszechnie znane jako zmiennoprzecinkowa podwójna precyzja. PHP wykorzystuje także zmiennoprzecinkowe punkty podwójnej precyzji.
64-bitowe liczby zmiennoprzecinkowe są takie, jak można się domyślić, przechowywane w 64 bitach, gdzie liczba (ułamek) jest przechowywana w bitach od 0 do 51, wykładnik w bitach od 52 do 62, a bit 63 w znaku.
Powoduje to problemy w linii, ponieważ oznacza, że liczby całkowite są liczone jako dokładne do 15 miejsc po przecinku i mogą w rzeczywistości obliczyć maksymalnie 17 miejsc po przecinku.
Oznacza to, że liczby mogą bardzo łatwo zaokrąglić liczbę lub mogą nie być poprawnie przechowywane.
var x = 999999999999999; // x = 999999999999999
var y = 9999999999999999; // y = 10000000000000000
Arytmetyka dla punktów zmiennoprzecinkowych może być również często nierównomierna w miejscach.Jak pokazałem powyżej; 0.1
w systemie dziesiętnym nie jest rzeczywisty 0.1
, ale 0.000110011...
i tak dalej. Oznacza to, że podstawowe matematyki mogą być całkowicie błędne.
var x = 0.2 + 0.1; // x = 0.30000000000000004
W końcu trzeba pomylić system, aby uzyskać pożądany numer. Można to zrobić przez *
liczbę przez 10
, a następnie dzieląc go, aby uzyskać rzeczywisty wynik poszukiwanych.
var x = (0.2 * 10 + 0.1 * 10)/10; // x = 0.3
Precision wewnątrz komputerów zmiennoprzecinkowe jest bardzo trudne, a jeszcze trudniejsze, gdy istnieje wiele różnych wdrożeń (lub przeglądarki) starają się dołożyć wszelkich starań dla prędkości i wyświetlanie informacji są one podane prawidłowo.
Istnieje sporo różnych informacji dotyczących zmiennoprzecinkowych oraz tego, co może się przydarzyć procesorowi CSS (lub JS, tak jak spodziewam się, że obliczenia będą takie same).
Prawdopodobnie właśnie IEEE zmiennoprzecinkowych problem. Nie przejmuj się tym. – Quentin
Ale jeśli sprawdzisz wartość hex/rgb wyjścia, to samo #efefef jako hex i rgb jako 239 .. Dane wyjściowe są takie same jak w innych przeglądarkach. Więc nie przeszkadzajcie w tym :) –