Вы столкнулись с MySQL ошибкой 87794 . Плавающее число хранится с полной точностью, но не возвращается клиенту с полной точностью.
MySQL использует константу FLT_DIG
(равную 6 с кодировкой IEEE 754) для печати числа типа float. FLT_DIG - это число десятичных цифр, которое можно преобразовать в двоичное число с плавающей запятой и обратно без потери точности для любого входного числа. Это не означает, что нет чисел с более значимыми цифрами, которые могут быть точно представлены в двоичном формате (и ваш случай является примером такого числа), но константа обеспечивает это свойство для всех входных данных.
Вы можете использовать несколько обходных путей.
Двоичный протокол
По умолчанию MySQL использует «текстовый протокол», который отправляет числа по проводам с использованием цифр ASCII. Это где FLT_DIG
имеет эффект. В отличие от этого, двоичный протокол отправляет 32-разрядные значения IEEE 754.
Я не знаю, может ли соединитель ODB C выставлять двоичный протокол, но MySqlConnector делает для подготовленных операторов .
using (var connection = new MySqlConnection("...;IgnorePrepare=false"))
{
// read float back
float floatRead;
using (var cmd = new MySqlCommand())
{
cmd.Connection = connection;
cmd.CommandText = "select SomeFloat from TestFloatTable";
// ADD THIS LINE
cmd.Prepare();
var reader = cmd.ExecuteReader();
reader.Read();
floatRead = (float)reader.GetValue(0); // GetValue returns a float object
}
}
Привести к двойной точности
Если выполнить вычисление для результата, MySQL приведет к двойной точности. Это будет правильно отформатировано на проводе, и ваш клиент прочитает правильный результат. Обратите внимание, что для MySqlConnector результирующее значение теперь будет напечатано как double
; вполне возможно, что разъем ODB C работает так же:
// read float back
float floatRead;
using (var cmd = new System.Data.Odbc.OdbcCommand())
{
cmd.Connection = connection;
// ADD "+0" TO THE SELECT STATEMENT
cmd.CommandText = "select SomeFloat+0 from TestFloatTable";
var reader = cmd.ExecuteReader();
reader.Read();
floatRead = (float)(double)reader.GetValue(0); // GetValue returns a double object
// ALTERNATIVELY, just use GetFloat
floatRead = reader.GetFloat(0);
}