Ява: двойной против поплавка - PullRequest
22 голосов
/ 24 апреля 2009

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

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

Не может ли double с быть float с?

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

Ответы [ 6 ]

32 голосов
/ 24 апреля 2009

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

z.b = 2.2f

'f' в конце числа делает его плавающим вместо двойного.

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

17 голосов
/ 24 апреля 2009

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

диапазон значений от 1.40129846432481707e-45 до 3.40282346638528860e+38

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

9 голосов
/ 24 апреля 2009

По умолчанию 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.

6 голосов
/ 25 апреля 2009

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

3 голосов
/ 24 апреля 2009
can't doubles be floats as well?

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

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

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

0 голосов
/ 29 сентября 2014

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

...