it-swarm.com.ru

Ява: двойной против поплавка

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

class Big {
  float b;
}

public class PassObject {
  static void f(Letter y) {
    y.c = 'z';
  } //end f()
  static void g(Big z) {
    z.b = 2.2;
  }

  public static void main(String[] args ) {
    Big t = new Big();
    t.b = 5.6;
    System.out.println("1: t.b : " + t.b);
    g(x);
    System.out.println("2: t.b: " + t.b);
  } //end main
}//end class

Выдает ошибку, говорящую «Возможна потеря точности».

PassObject.Java:13: possible loss of precision
found: double
required : float   z.b = 2.2
passobject.Java:20: possible loss of precision
found : double
required : float   t.b = 5.6

Разве doubles не может быть floats также?

заранее спасибо

22
phill

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

z.b = 2.2f

Буква «f» в конце числа превращает его в число с плавающей точкой вместо двойного.

Java не будет автоматически сужать двойное число до числа с плавающей точкой.

32
mipadi

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

диапазон с плавающей запятой от 1.40129846432481707e-45 до 3.40282346638528860e+38

двойной диапазон от 4.94065645841246544e-324d до 1.79769313486231570e+308d

17
Powerlord

По умолчанию Java будет обрабатывать десятичную дробь (например, «4.3») как double, если вы не укажете float, добавив f после числа (например, «4.3f»).

У вас одна и та же проблема в обеих строках. Во-первых, десятичный литерал интерпретируется компилятором как двойной. Затем он пытается присвоить его b, который имеет тип float. Поскольку double составляет 64 бита, а float только 32 бита (см. документация по примитивам Java ), Java выдает ошибку, указывающую, что float не может поместиться внутри double. Решение состоит в том, чтобы добавить f к вашим десятичным литералам.

Если вы пытаетесь сделать обратное (то есть назначить float для double), это будет нормально, поскольку вы можете разместить 32 бита float в 64 double.

9
mtlynch

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

6
Peter Lawrey
can't doubles be floats as well?

Нет. Каждое значение или переменная имеет ровно один тип (double, float, int, long и т.д.). Спецификация языка Java точно описывает, что происходит, когда вы пытаетесь присвоить значение одного типа переменной другого типа. Как правило, присваивания «меньшего» значения «большему» типу допускаются и выполняются неявно, но присваивания, в которых информация может быть потеряна, поскольку целевой тип слишком «мал», чтобы содержать все значения типа Origin, не допускаются компилятор, даже если конкретное значение вписывается в целевой тип.

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

Одной из областей, которая часто вызывает путаницу, являются вычисления, потому что они неявно «расширены» до int по техническим причинам. Таким образом, если вы умножите два коротких и попытаетесь присвоить результат короткому, компилятор будет жаловаться, потому что результатом вычисления является int.

3
Michael Borgwardt

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

0
sumanta