Подтвердить что ты не робот

Всегда ли возврат к двойному плаванию возвращает значение?

Выполняет ли листинг double до float одинаковый результат или могут быть некоторые "округляющие различия"?

Например, x в

float x = (float)0.123456789d;

всегда одно и то же значение?

А как насчет того, чтобы сбрасывать float в double, а затем отбрасывать его обратно на float, т.е. (float)(double)someFloat?

В основном заинтересованы в том, что результаты на С#, но не стесняйтесь делиться, если у вас есть знания о том, как это работает на других языках.

4b9b3361

Ответ 1

Результаты не должны зависеть от языка, если язык не отличается от спецификации IEEE.

Все поплавки могут быть точно представлены как удвоенные, поэтому в оба конца от float до double to float должно быть такое же значение, с которого вы начали.

Аналогично, при любом добавлении значения double для float всегда должен быть одинаковый результат, но, конечно, существует много разных двойных значений, которые усекаются до одного и того же значения float.

Ответ 2

Если вы отбрасываете double до float, вы теряете точность и данные. Upcasting a float до a double является расширяющимся преобразованием; никакие данные не теряются, если они затем сработали с округлением... то есть, если вы не сделаете что-то по значению до того, как он сбрасывает его обратно в float.

Числа с плавающей запятой жертвуют точностью и точностью для диапазона. Одноточечные поплавки дают вам 32-битную точность; двойная точность дает вам 64 бит. Но они могут представлять значения за пределами границ, которые укажет базовая точность.

С# float и double - значения с плавающей запятой IEEE 754.

Эффективная точность мантиссы на 1 бит больше, чем ее кажущийся размер (магия с плавающей запятой).

Некоторые ресурсы с плавающей запятой CLR для вас:

Эта статья, вероятно, является канонической статьей об опасностях и ловушках арифметики с плавающей запятой. Если вы не являетесь членом ACM, нажмите ссылку на заголовок, чтобы найти общедоступную загрузку статьи:

  • Дэвид Голдберг. 1991. Что каждый компьютерный ученый должен знать о арифметике с плавающей запятой. ACM Comput. Surv. 23, 1 (март 1991 года), 5-48. DOI = 10.1145/103162.103163 http://doi.acm.org/10.1145/103162.103163

    Абстрактный
    Арифметика с плавающей точкой рассматривается многими как эзотерический субъект. Это довольно удивительно, поскольку плавающая точка вездесуща в компьютерных системах: Почти каждый язык имеет тип данных с плавающей запятой; компьютеров с ПК до суперкомпьютеры имеют ускорители с плавающей запятой; большинство компиляторов будут время от времени компилировать алгоритмы с плавающей запятой; и практически каждый система должна реагировать на исключения с плавающей запятой, такие как переполнение. Эта бумага представляет учебное пособие по аспектам с плавающей точкой, которые оказывают непосредственное влияние на дизайнеров компьютерных систем. Он начинается с фона с плавающей точкой ошибки представления и округления, продолжается с обсуждением плавающего IEEE и заканчивается примерами того, как разработчики компьютерных систем могут лучше поддерживать плавающие точки.

Ответ 3

Двойной должен иметь возможность точно удерживать все возможные значения поплавка. Приведение float в double не должно изменять значение, а возврат к float должен возвращать исходное значение, если вы не выполняли никаких вычислений в double в то же время.

Ответ 4

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

Операции с плавающей точкой, особенно литье, всегда являются предметом усечения/округления и любого другого приближения.

Ответ 5

В некоторых случаях самое близкое представление float к числовой величине может отличаться от значения, полученного округлением ближайшего представления double до float. Две такие величины: 12 344 321,4999999991 и 12,345,678.50000000093. Целочисленные числа выше и ниже обеих этих величин точно представлены как float, но ближайший double к каждому из них имеет дробную часть ровно 0,5. Поскольку преобразование таких значений double (между 2 ^ 23 и 2 ^ 24, с долей от 0,5) до float будет округлено до ближайшего четного целого; компилятор в каждом случае заканчивает округление от значения, которое было бы ближе к исходному номеру.

Обратите внимание, что на практике компилятор, по-видимому, анализирует числа как double, а затем преобразовывается в float, поэтому хотя 12344321.4999999991f должен округлить до 12344321f, он округляется до 12344322f. Аналогично, 12345678.50000000093f должен округлить до 12345679f, но раундов до 12345678f, поэтому даже в случаях, когда конверсия в double, а затем float теряет точность, таких потерь при конверсиях нельзя избежать, указав числа непосредственно как float.

Кстати, значения 12344321.4999999992f и 12345678.50000000094f округлены правильно.

Ответ 6

Числа с плавающей запятой в С# хранятся в формате IEEE 754 (http://en.wikipedia.org/wiki/IEEE_754). Этот формат состоит из двух частей: цифр и экспоненты. Удвоенные номера содержат 52 цифры, а поплавки - 23 цифры. База - 2, а не десять. Итак, для вашего примера выше (0.123456789) цифры будут 111010110111100110100010101 (двоичное представление 123456789). Это 27 цифр, которые удобно вписываются в двойной, но не в поплавок, так что да, точность будет потеряна при конвертации в оба конца.

С другой стороны, если ваш номер равен 0.123456, цифры будут 11110001001000000 (17 цифр), которые удобно помещаются как в поплавке, так и в десятичной системе, поэтому вы не теряете точности в обратном направлении.

Ответ 7

Это скомпилировано с gcc на mac.,,

#include <stdio.h> 
int main()
{
    double x = 0.123456789;
    float y = x;
    double z = y;

    printf ("x=%9.9f\n",x);
    printf ("y=%9.9f\n",y);
    printf ("z=%9.9f\n",z);
}

Выплевывает это.,

./a.out 
x=0.123456789
y=0.123456791
z=0.123456791