C# с плавающей запятой для двойного преобразования - PullRequest
1 голос
/ 16 января 2020

Когда я выполняю следующее деление и разыгрываю на плаву, я получаю следующее значение:

float fltval = (float)(1183588296 / 65536.0);   //18060.125

Выполнение того же деления без разыгрыша дает следующее двойное значение:

double dblval = 1183588296 / 65536.0;   //18060.124145507813

Могу ли я найти ближайшее двойное значение для данного значения с плавающей запятой?

Когда я делаю следующее:

double nearestdbl = (double)fltval;

Я получаю само значение с плавающей запятой, а не ближайшее двойное значение:

//nearestdbl = 18060.125

Как я могу получить более точное значение (18060.124145507813) или более близкое значение в этом случае?

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

Однако следующий код дает более точное двойное значение:

float f = 125.32f;  //125.32
double d = (double)125.32f; //125.31999969482422

Почему он находит более близкое значение во 2-м примере, а не в 1-м примере?

Спасибо.

Ответы [ 3 ]

1 голос
/ 16 января 2020

(На самом деле, когда я запускаю код, я получил 18060.13 вместо 18060.125, но я буду продолжать использовать последний в своем ответе.)

Могу ли я найти ближайший двойник значение для данного значения с плавающей запятой?

Вам, кажется, почему-то кажется, что ближайшее двойное значение для поплавка 18060.125 равно 18060.124145507813? Это неправда. Ближайшее двойное значение для числа с плавающей точкой 18060.125 равно 18060.125. Это значение может быть одинаково точно представлено double и float.

Почему приведение 18060.124145507813 к float дает 18060.125 тогда?

Потому что ближайший float к double 18060.124145507813 равен 18060.125. Обратите внимание, что это наоборот из вашего понимания. Это не означает, что ближайшим double к float 18060.125 является 18060.124145507813, поскольку между двумя смежными float значениями существует много double значений.

Невозможно go обратно к "double, от которого вы получили float", потому что когда вы преобразуете в float, вы теряете информацию. Вы конвертируете 64-битное значение в 32-битное. Эта информация не возвращается.

Почему тогда работает приведение 125.32f?

Поскольку float не может представлять число 125.32 так же точно, как double, поэтому при приведении к удвоению он пытается приблизить его еще дальше. Хотя может показаться, что float может точно представлять 125.32 100%, это всего лишь иллюзия, созданная методом ToString. Всегда форматируйте числа с плавающей запятой каким-либо способом форматирования, например string.Format.

0 голосов
/ 16 января 2020

Когда вы конвертируете double в float, значение double округляется до ближайшего значения float. Если значение типа double слишком мало или слишком велико, чтобы вписываться в тип с плавающей точкой, результат равен нулю или бесконечности. проверить эту ссылку: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/numeric-conversions

0 голосов
/ 16 января 2020

При преобразовании типов данных вы всегда получите тип с меньшей точностью ... Рассмотрим случай преобразования int в двойное

int intVal = (int)(10.0/4);
double dblVal = 10.0/4;
//dblVal = 2.5 --- intVal = 2
dblVal = intVal;
//dblVal = 2.00;

Итог: вы не можете сохранить память и сохранить точность одновременно ...

...