Подтвердить что ты не робот

Почему Google Chrome изменяет непрозрачность фона?

Я использую следующее правило CSS для установки цвета фона div:

div {
    background-color: rgba(96, 96, 96, .1);
}

В Google Chrome v.42 на вкладке "Вычислить" в Инструментах разработчика я вижу этот результат rgba(96, 96, 96, 0.0980392);. Я думаю, это похоже на оптимизацию веб-набора...

В FireFox v.36 вычисленный фоновый цвет равен rgba(96, 96, 96, 0.1)

Я сделал простой http://jsfiddle.net/sergfry/c7Lzf5v2/, который показывает его в действии.

Итак, могу ли я предотвратить изменение непрозрачности в Google Chrome?

Спасибо!

4b9b3361

Ответ 1

Как указано Quentin, это проблема с плавающей точкой IEEE.

0.1 фактически не существует в десятичной плавающей запятой технически просто из-за того, как работает двоичный файл.

0.1 - одна десятая, или 1/10. Чтобы показать его в двоичном формате, разделите двоичный код 1 на двоичный код 1010, используя двоичное длинное деление:

enter image description here

Как вы можете видеть, 0.1 в двоичном формате 0.0001100110011....0011, и он будет продолжать повторять 0011 в конце до бесконечности.

Браузеры выбирают ближайшую доступную точку для 0.1 и используют ее как непрозрачность. Некоторые перейдут, а некоторые подойдут.

FireFox я бы догадался, что он просто показывает читаемую человеком версию, но на самом деле ее действительно использует плавающую точку, пригодную для использования компьютером.

В качестве примера:

body {
    color: rgba(0,0,0,0.1); // actually 0.0980392
    opacity: 0.1; // actually 0.100000001490116
}

Два совершенно разных значения для одной и той же точки с плавающей запятой.

Эта проблема с плавающей запятой действительно может быть реплицирована в другом месте в браузерах, используя другие языки, такие как Javascript. Номера Javascript всегда 64-битные с плавающей запятой (что, я считаю, CSS тоже). Это более широко известно как плавающая точка с двойной точностью. PHP также использует плавающие точки с двойной точностью.

64-битные числа с плавающей запятой, как вы могли догадаться, хранились в 64 битах, где число (дроби) хранится в битах от 0 до 51, показатель в битах 52-62 и знаковый бит 63.

Это вызывает проблемы в строке, так как это означает, что целые числа считаются точными до 15 десятичных точек и могут действительно вычислять до 17 десятичных точек.

Это означает, что числа могут округляться очень легко или просто не могут быть сохранены правильно.

var x = 999999999999999;  // x = 999999999999999
var y = 9999999999999999; // y = 10000000000000000

Арифметика для плавающих точек также может быть вне выравнивания довольно много в местах. Как я показал выше; 0.1 в десятичном значении не актуально 0.1, но 0.000110011... и т.д. Это означает, что некоторые основные математические данные могут быть совершенно неправильными.

var x = 0.2 + 0.1; // x = 0.30000000000000004

В итоге вам придется запутать систему, чтобы получить нужный номер. Это можно сделать * числом 10 и затем делить его, чтобы получить ваш фактический желаемый результат.

var x = (0.2 * 10 + 0.1 * 10) / 10; // x = 0.3

Точность в плавающей точке компьютеров очень сложна и еще сложнее, когда существует множество различных реализаций (или браузеров), пытающихся сделать все возможное для скорости и отображения информации, которую они получили правильно.

Существует довольно много разных частей информации о плавающих точках и то, что может пытаться достигнуть процессор CSS (или JS, как я ожидаю, будут вычисления одинаковыми).