Автоматическое литье - PullRequest
6 голосов
/ 15 августа 2011

Мне нужно написать программу, которая получает от пользователя число n, а затем вычисляет сумму: s = 1/1 + 1/2 + ... + 1 / n.

Я написал этот код:

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner unos = new Scanner(System.in);
        System.out.println("n=?");
        int n = unos.nextInt();

        double s = 0.0;
        for (int i = 1; i <= n; i++) {
            s = s + (1.0 / i);
        }
        System.out.println("s=" + s);
    }
}

Как Java решает преобразовать значение int i в double в этом выражении:

s = s + (1.0 / i);

Ответы [ 6 ]

9 голосов
/ 15 августа 2011

Правила, определяющие, какой тип преобразуется / переводится в какой-либо другой тип, определены в Спецификации языка Java Глава 5 - Преобразования и продвижения .

Специально для большинства арифметических операций см.в разделе Двоичное числовое продвижение .

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

  • Если один из операндов имеет тип double, другой преобразуется в двойной.
  • В противном случае, если один из операндов имеет тип float, другой преобразуется в float.

В вашем случае 1.0 является двойным, поэтому i преобразуется в двойной (расширяющее преобразование).Поскольку s уже является двойным, дальнейшее преобразование не требуется.

5 голосов
/ 15 августа 2011

, если нет совпадения между типами (и деление двойного на int не совпадает), он выбирает одно из следующих значений (1) с наивысшим приоритетом:

(1) identity conversion
(2) a widening primitive conversion
(3) a widening reference conversion 
(4) a boxing conversion optionally followed by a widening reference conversion
(5) an unboxing conversion optionally followed by a widening primitive conversion. 

в этом случаеВыбрал (2) расширяющиеся примитивы.Он не меняет double на int, потому что double-> int не является ни тождеством, ни расширением, поэтому единственный левый выбор - это расширение int до double

больше информации: http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#184206

3 голосов
/ 15 августа 2011

При выполнении арифметики в отличие от типов Java имеет тенденцию расширять задействованные типы, чтобы избежать потери информации.

Если одна из переменных является двойной, тогда java обрабатывает обе переменные как двойные.

Проверьте этот пост очистить все ваши сомнения:

1 голос
/ 15 августа 2011

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

1 голос
/ 15 августа 2011

Он просто переводит i к ближайшему значению double перед делением.

См. Раздел спецификации языка Java 5.1.2 Расширение преобразования примитивов для получения подробной информации.

Правило разрыва связи, которое является еще менее смещенным, является круглой половиной к четному, а именно:

Если доля y равна 0,5, то q является четным целым числом, ближайшим к y.

Таким образом, например, +23,5 становится +24, +22,5 становится +22, -22,5 становится -22, и -23,5 становится -24.

Этот метод также обрабатывает положительные и отрицательные значения симметрично и поэтому не имеет общего смещения, если исходные числа являются положительными или отрицательными с равной вероятностью.Кроме того, для наиболее разумного распределения значений y ожидаемое (среднее) значение округленных чисел, по существу, такое же, как и для исходных чисел, даже если последние все положительные (или все отрицательные).Тем не менее, это правило будет по-прежнему вводить положительное смещение для четных чисел (включая ноль) и отрицательное смещение для нечетных.

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

Это режим округления по умолчанию, используемый в вычислительных функциях и операторах IEEE 754.

Источник: Википедия

0 голосов
/ 22 февраля 2016

Правило очень простое

  1. Сначала проверяется, является ли один из операндов двойным, если это правда затем он преобразует не двойной операнд в двойной диапазон
  2. Если первое утверждение ложно, то проверяется, операнды являются типом с плавающей запятой, если это правда, тогда он преобразует операнд с плавающей точкой в ​​диапазон с плавающей точкой.
  3. Если ничего из вышеперечисленного, то java сохраняет тип как есть

См. Код ниже, чтобы понять более ясно

public static void main(String[] args) {
    int int_val = 20;
    double doub_val = 20.0;
    float flo_val = 20.0f;

    /* lets see the first statement of my answer is true  */
    //## 1.0 I'm dividing double / float 
    System.out.println(((Object)(doub_val/flo_val)).getClass().getName());
    //## 1.1 I'm dividing double / int 
    System.out.println(((Object)(doub_val/int_val)).getClass().getName());

    //## 2.0 I'm dividing float / int 
    System.out.println(((Object)(flo_val/10)).getClass().getName());

    //## 3.0 I'm dividing int / int 
    System.out.println(((Object)(int_val/10)).getClass().getName());
    //## 3.1 I'm dividing double / double 
    System.out.println(((Object)(doub_val/10.0)).getClass().getName());
    //## 3.2 I'm dividing float / float 
    System.out.println(((Object)(flo_val/10.0f)).getClass().getName());

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...