Я должен упомянуть, что эта база данных была перенесена из базы данных MySQL, в этом случае тип был float. Когда я использовал модуль MySQLdb для извлечения данных из этой таблицы MySQL, он получил 0,76, как и ожидалось.
Это не проблема, вызванная pyodbc. Разница между MySQL и MSSQL заключается в том, что числа с плавающей запятой отображаются .
0,76 не является значением, которое может быть представлено точно как 32-разрядная с плавающей запятой ("одинарная точность "). Как этот сайт (и другие) скажет вам, наиболее точное представление этого числа - 7,599999904632568359375E-1, так что именно это хранят обе базы данных (внутренне представленные как 0x3F428F5C).
При получении значения MSSQL возвращает фактическое значение, которое было записано в базу данных. Вот почему он возвращается как 0,7599999904632568.
С другой стороны, MySQL возвращает самую короткую строку, представляющую значение с плавающей запятой , что приведет к заданному сохраненному значению . Как описано в документации :
F -> D преобразование выполняется с максимально возможной точностью, возвращая D как самую короткую строку, которая возвращает F при чтении обратно и округляется досамое близкое значение в собственном двоичном формате, как определено IEEE.
Итак, MySQL выполняет циклическое переключение 0,76, потому что это просто самое короткое значение, соответствующее значению с плавающей запятой, внутреннее представление которого равно 0x3F428F5C. Это можно проиллюстрировать, протестировав число, очень близкое к 0,76, но не совсем равное:
is_mssql = (cnxn.getinfo(pyodbc.SQL_DRIVER_NAME) == 'msodbcsql17.dll')
crsr = cnxn.cursor()
test_value = '0.7599999905'
if is_mssql:
crsr.execute("CREATE TABLE #foo (x real)")
crsr.execute(f"INSERT INTO #foo (x) VALUES ('{test_value}')")
result = crsr.execute("SELECT x FROM #foo").fetchval()
else:
crsr.execute("CREATE TEMPORARY TABLE foo (x float(23))")
crsr.execute(f"INSERT INTO foo (x) VALUES ('{test_value}')")
result = crsr.execute("SELECT x FROM foo").fetchval()
print(f'{"MSSQL" if is_mssql else "MySQL"} returned {result}')
Несмотря на то, что 0,7599999905 является «фактическим» значением, MySQL по-прежнему возвращает 0,76, а MSSQL по-прежнему возвращает 0,7599999904632568.