Представление плавания оценивает в Java

Посмотрите на эти три строки кода ниже.

  float f = 1;

  float g = 1.1;

  float h = 1.1f;

Вторая строка имеет ошибки компиляции, в то время как другие строки не имеют ошибок компиляции. Первая строка хорошо работает без суффикса f, и третья строка работает с суффиксом f. Почему это?

9
задан Peter O. 14 January 2013 в 23:11
поделиться

4 ответа

Литералы с плавающей точкой в Java по умолчанию являются двойными значениями.

JLS 3.10.2 Литералы с плавающей точкой

Литерал с плавающей точкой имеет тип float, если он имеет суффикс в виде буквы ASCII F или f; в противном случае его тип - double, и он может быть дополнен суффиксом в виде буквы ASCII D или d.

Вы не можете присвоить значение double значению float без явного сужающего преобразования. Поэтому у вас есть два варианта:

  • Для литералов используйте суффикс f или F для обозначения значения float
  • Для нелитералов используйте явное приведение (float)

Примером последнего является:

double d = 1.1;
float f = (float) d; // compiles fine!

О расширяющих преобразованиях

Причина, по которой это компилируется:

float f = 1;

заключается в том, что расширяющее преобразование из int в float может быть выполнено неявно в контексте присваивания.

JLS 5.2 Преобразование присваивания

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

  • расширяющее примитивное преобразование (§5.1.2)
  • [...]

JLS 5.1.2 Расширяющееся примитивное преобразование

Следующие 19 специфических преобразований примитивных типов называются расширяющимися примитивными преобразованиями:

  • int в long, float или double
  • [...]

Другие суффиксы типов данных для литералов

Как упоминалось выше, существует также суффикс D или d для double. Рассмотрим этот фрагмент для примера:

static void f(int i) {
    System.out.println("(int)");
}
static void f(double d) {
    System.out.println("(double)");
}

//...
f(1);   // prints "(int)"
f(1D);  // prints "(double)"

Существует также суффикс для длинных литералов, это L или l (строчная буква). Настоятельно рекомендуется использовать прописную букву.

JLS 3.10.1 Целочисленные литералы

Целочисленный литерал имеет тип long, если он имеет суффикс в виде буквы ASCII L или l (ell); в противном случае он имеет тип int. Суффикс L является предпочтительным, поскольку букву l (ell) часто трудно отличить от цифры 1 (one).

22
ответ дан 4 December 2019 в 07:34
поделиться

Вы присваиваете значение double объекту переменная типа float . 1.1 сам по себе (без прикрепленного к концу f ) предполагается компилятором как имеющий тип double . Компилятор не любит делать неявные понижающие преобразования, потому что там есть вероятность потери точности.

7
ответ дан 4 December 2019 в 07:34
поделиться

Первая строка автоматически передает int в float (ok).

Вторая строка не могла преобразовать double в float из-за потери точности. Вы должны преобразовать:

float g = (float) 1.1;

Третья строка не требует преобразования.

0
ответ дан 4 December 2019 в 07:34
поделиться

В Java каждое число с плавающей точкой (любое число с десятичной точкой) по умолчанию имеет вид double, который является более точным, чем float. И по умолчанию Java не позволяет преобразовывать double в float из-за потери точности.

Вы все еще можете присвоить double к float путем приведения:

float g = (float) 1.1;
0
ответ дан 4 December 2019 в 07:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: