Представление значений 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 конкретных преобразований для примитивных типов называются расширяющегося примитивного преобразования:
int
tolong
,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;