Представление значений float в Java

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

  float f = 1;

  float g = 1.1;

  float h = 1.1f;

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

4 ответов


литералы с плавающей запятой в Java-это double значение по умолчанию.

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 to float может быть сделано неявно в контексте задания.

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

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

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

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

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

  • int to 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)"

есть также суффикс long литералы, то есть L или l (строчная буква). Это рекомендуется что вы используете заглавные вариант.

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

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


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


первый autocasts линии типа int к типу float (ОК).

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

float g = (float) 1.1;

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


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

вы все еще можете назначить double до float методом литья:

float g = (float) 1.1;