Представление значений float в Java
посмотрите на три строки кода ниже.
float f = 1;
float g = 1.1;
float h = 1.1f;
вторая строка содержит ошибки компиляции, в то время как другие строки не имеют ошибок компиляции. Первая строка работает нормально без суффикса f, а третья строка работает с суффиксом f. Почему так?
4 ответов
литералы с плавающей запятой в Java-это double значение по умолчанию.
JLS 3.10.2 литералы с плавающей запятой
литерал с плавающей запятой имеет тип
floatесли это суффикс с буквой ASCIIFили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 конкретных преобразований для примитивных типов называются расширяющегося примитивного преобразования:
inttolong,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если он имеет суффикс с буквой ASCIILили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;