2015-10-18 3 views
1

Я удивлен увидеть ниже разницы в Java:Почему точность потеряна для двойного литья в Java?

(double)(int1/int2) // return 0.0 - precision lost. 

(double)int1/int2 // return 9.3123325E-10 - precision kept. 

ли дизайн, что кронштейн в первом выражении делает оценки теряют точность?

+0

скобка это сделать. –

+0

были бы полезны значения 'int1' и' int2' – gefei

+0

Вы используете целочисленные математические вычисления в первом примере (затем литье в двойное), двойные математические вычисления во втором.Это действительно по дизайну –

ответ

2

Да, это по дизайну. Поместив выражение в parens, вы измените нормальный приоритет, так что сначала будет выполняться int1/int2, и поскольку оба являются (предположительно) целыми числами, используйте целочисленное деление, которое усекает результат до целого числа. Во втором случае применяется нормальный приоритет, поэтому int1 сначала преобразуется в double, затем выполняется разделение с использованием деления с плавающей запятой.

2

Это вопрос order-of-operations. Скобки имеют более высокий приоритет, чем приводы, поэтому первый оператор будет выполнять операции в скобках в первую очередь - он передает частное значение double.

Отливки имеют более высокий приоритет, чем деление, поэтому в вашем втором заявлении отливка применяется до операция деления.

0

В первом вы делаете целочисленное деление, а затем бросаете в двойное. Так как целочисленное деление усекает любые десятичные числа, вы теряете десятичный бит ответа, а отбрасывание его в double не возвращает эту информацию.

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

Второй эквивалент ((double) int1)/int2, поскольку отливки имеют более высокий приоритет, чем /.

1

Из-за скобки (double)(int1/int2) сначала выполняет целочисленное деление (точность теряют включен), а затем преобразует результат в двойной.

(double)int1/int2 выполняет двойное деление, потому что первый операнд double.

1

Абсолютно. В заявлении 1 вы выполняете разделение, а затем выполняете его. В заявлении 2 вы сначала бросаете int1 в double, тогда вы выполняете деление, которое продвигает int2 до double и точность сохраняется.

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

0

Я считаю, что это связано с тем, что скобки (за PEMDAS) заставляют вычисление происходить в скобках до того, как происходит бросок, и как таковое, десятичное значение, если деление меньше 1, равно 0.

Пример:

(двойной) (3/5) = (дважды) 0; (Так как Int не может быть .6)

Но (двойной) 3/5 -> (двойной) +0,6

Смежные вопросы