Я предполагаю, что это произошло раньше, но я не смог найти ответ на мой вопрос. Вот небольшой фрагмент кода:
$stmt = $this -> db -> query(" SELECT `Field` FROM `Table` WHERE (`ID` = 33608)"); var_dump($stmt -> fetch());
И это результат, который я получаю:
array(1) { ["Field"]=> float(1.7999999523163) }
Однако данные в базе данных MySQL составляют 1,8. Тип поля – float (7,4). $ this-> db – объект PDO. Недавно я перешел на PDO (из AdoDB), и этот код работал нормально. Я не уверен, что пошло не так. Не могли бы вы указать мне в правильном направлении? Благодаря!
Как указано в типах с плавающей запятой (приблизительное значение) – FLOAT
, DOUBLE
:
MySQL выполняет округление при сохранении значений, поэтому, если вы вставляете
999.00009
в999.00009
FLOAT(7,4)
, приблизительный результат равен999.0001
.Поскольку значения с плавающей запятой являются приблизительными и не сохраняются в виде точных значений, попытки рассматривать их как точные в сравнении могут привести к проблемам. Они также зависят от зависимостей платформы или реализации. Для получения дополнительной информации см. Раздел C.5.5.8, «Проблемы с значениями с плавающей запятой»
Для максимальной переносимости код, требующий хранения приблизительных значений числовых данных, должен использовать
FLOAT
илиDOUBLE PRECISION
без указания точности или количества цифр.
Поэтому при вставке 1.8
в вашу базу данных MySQL округлял литерал до 001.8000
и кодировал ближайшее приближение к этому номеру в формате binary32 : то есть 0x3FE66666
, чьи биты означают:
Знак : 0b0 Предвзятый показатель : 0b01111111 = 127 (представление включает смещение +127, поэтому exp = 0) Значение : 0b [1.] 11001100110011001100110 ^ скрытый бит, не сохраненный в двоичном представлении = [1.] 7999999523162841796875
Это соответствует:
(-1) ^ 0 * 1.7999999523162841796875 * 2 ^ 0 = 1,7999999523162841796875
Это значение, которое MySQL возвращает клиенту. Похоже, что AdoDB затем проверял тип данных столбца и соответствующим образом округлял результат, тогда как PDO этого не делает.
Если вам нужны точные значения, вы должны использовать тип данных с фиксированной точкой , например DECIMAL
.
Вы должны использовать тип поля DECIMAL
вместо FLOAT
если хотите точные значения.
И PDO не имеет к этому никакого отношения. Это скорее связано с тем, как компьютеры работают в целом.