Я предполагаю, что это произошло раньше, но я не смог найти ответ на мой вопрос. Вот небольшой фрагмент кода:
$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.00009FLOAT(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 не имеет к этому никакого отношения. Это скорее связано с тем, как компьютеры работают в целом.