Как объединить два int (ов) в double в JAVA?

Если у меня есть:

int a = 123;
int b = 456;

Как я могу получить?:

double c = 123.456;
 Ignacio Garat03 июн. 2016 г., 16:39
@Thomas Я соединяю два целых, один из MeterNumberPicker, а другой для CentimeterNumberPicker
 Tunaki03 июн. 2016 г., 16:42
Связанные с C #stackoverflow.com/q/18432640/1743880
 Cache Staheli03 июн. 2016 г., 16:35
Вы пытались умножить второе число на что-то вроде.001 а затем добавить это к первому?
 duffymo03 июн. 2016 г., 16:37
Может быть класс Money с дробными и целыми частями. Вам нужен общий способ получить размер делителя для дробной части.
 Thomas03 июн. 2016 г., 16:34
Что ты пробовал? Было быint a = 1; int b = 23456; результат в1.23456? Что вы на самом деле пытаетесь сделать / для чего вы это используете?
 duffymo03 июн. 2016 г., 19:42
Я бы сказал, что это плохой дизайн, потому что у него нет понимания единиц. Если вы инкапсулируете это в объект Length, который имеет скалярное значение и единицы, инкапсулированные вместе, это было бы намного лучше. Мартин Фаулер не будет кричать на тебя. Вы также можете заключить перевод единиц измерения (например, метры в фарлонги и т. Д.)martinfowler.com/eaaDev/quantity.html

Ответы на вопрос(6)

Если размерb не является обязательным, просто инициализируйте новую оболочку:

new Double(a + ((double)b / 1000))

Обратите внимание, что я кастуюb вdouble здесь, чтобы получитьdouble ценностьb / 1000 вместо целочисленного значения.

 Mena03 июн. 2016 г., 16:37
@FredK прочитайте ответ: «Если размер b не является случайным»
 Dmitry Bychenko03 июн. 2016 г., 16:38
1000.0, пожалуйста отметьте.0
 Mena03 июн. 2016 г., 16:40
@DmitryBychenko да, если вы приведете явноb вdouble вам не нужно использовать второй термин в качестве явногоdouble, Тем не менее, ваш путь чувствует себя немного более элегантным.
 FredK03 июн. 2016 г., 16:37
Что если b = 453798097654? знаменатель 1000 не будет работать.
 Andy Turner03 июн. 2016 г., 16:38
@DmitryBychenko1000. будет работать тоже.

а не тот, который предполагает преобразование между строкой и числовой формой, то вы можете сделать это:

double concatToDouble(int integer, int fraction) {
    if (fraction < 0) {
        throw new NumberFormatException("The fractional part must not be negative");
    } else if (fraction == 0) {
        return integer;
    } else {
        int numFractionDigits = (int) Math.log10(fraction) + 1;
        int scaleFactor = (int) (Math.pow(10, numFractionDigits) + 0.1);

        return (double) ((long) integer * scaleFactor
                + (long) Math.signum(integer) * fraction)
                / scaleFactor;
    }
}

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

Вычислительные заметки:

пересчетвверх целочисленная часть, выполняющаяцелое число сложение, а затем масштабированиевниз сумма даст вам наиболее близкий результат кdouble хочешь, ново многих случаях,double не имеетточный представление десятичного числа, которое вы хотите сформировать.Я выбрал типы тщательно и намеренно. В частности, я конвертирую значениеinteger печататьlong перед вычислением масштабированного значения, чтобы избежать переполнения.Math.signum() возвращает 1.0 для аргументов больше 0 и -1.0 для аргументов меньше нуля. Это позволяет методу обрабатывать отрицательные значенияinteger изящно.Я добавляю 0.1 к результатуMath.pow() перед усечением результата до целого числа в случае, если результатpow(), что не обязательно точно, немного меньше, чем точный результат.

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

 Arjan03 июн. 2016 г., 17:21
Хорошо, потому что он проверяет на отрицательные входные данные. Не приятно, что он не компилируется, потому что отсутствует; иUncompilable source code - incompatible types: possible lossy conversion from double to int ошибка компилятора. Редактирование, которое вы отклонили как «лишнее», фактически заставило его скомпилироваться и работать. Что «лишнего» в том, чтобы заставить код на самом деле компилироваться? Код больше не требуется для компиляции?
 Arjan03 июн. 2016 г., 21:16
Спасибо за разъяснения по поводу редактирования, и да, ваши изменения превратили это в отличный ответ и объяснение :) Я немного скептически отношусь к "лучшей производительности". Я пробежалтесты время строки и математические решения для различных диапазонов целых чисел и не могу сказать, что математическое решениеБыстрее, Возможно Math.pow не дешево? В любом случае +1 за отличный ответ :)
 John Bollinger03 июн. 2016 г., 18:17
@ Томас, вся арифметика в конечном вычислениицелое число арифметика, кроме деления в конце. Целочисленная арифметика является точной, и именно поэтому она здесь предпочтительнее.
 John Bollinger03 июн. 2016 г., 17:37
@Arjan, твоя редакция была бы намного лучше в форме комментария, который ты сделал потом. Редактирование ответов редко принимается хорошо. В любом случае, я сам находился в процессе серии правок. Я думаю, вы обнаружите, что выявленные вами проблемы теперь решены, а затем и некоторые.
 Thomas03 июн. 2016 г., 17:58
+1 для размышления о проблемах точности (например, эпсилон-части), отрицательных целочисленных частей и ведущих нулей в дробной части. Хотя один вопрос: не(integer * scale + fraction) / scale (Я намеренно пропустил часть Signum) есть больше проблем с точностью, чемinteger + (fraction / scale)? Двойная точность AFAIK должна быть максимальной для значений в диапазоне [0,1].
 Thomas06 июн. 2016 г., 09:42
Хм даinteger + (fraction / scale) будет иметь еще одну двойную операцию -add, Тем не менее, преобразование больших длинных значений в удвоенные значения в конечном итоге также приведет к потере точности, так что, вероятно, разница не так уж велика. Я провел несколько тестов, которые показывают, что вы получаете различия точности только для очень больших целочисленных и дробных частей, и в тех случаях, когда подход имел лучшую точность, зависел от начальных значений.
Решение Вопроса

Как насчет этого:

int a = 123; int b = 456;
double c = Double.parseDouble(a + "." + b);
 Dmitry Bychenko03 июн. 2016 г., 16:52
Самый простой способ, +1
 Thomas03 июн. 2016 г., 16:56
Так как он использует сборщик чисел, он может иметь строки, которые разбиты на целые. Если это так, то можно просто пропустить эту целочисленную часть синтаксического анализа - в любом случае это, вероятно, все еще самый простой подход. Таким образом +1

public class TestStackOverflowQuestion {

    public static void main(String[] args) {
        int a = 123;
        int b = 456;
        double c = a + Double.parseDouble("." + b);
        System.out.println(c);
    }
}
 Arjan03 июн. 2016 г., 16:44
@ Том, потому что нет необходимости создавать полный номер в строке и анализировать это ... так зачем мне?
 Tom03 июн. 2016 г., 16:40
Почему вы анализируете только двойное число вместо создания полного числа в строке и разбираете это?

Математическое решение

  int a = 123; 
  int b = 456;

  double c = a + (b == 0 ? 0 : b / Math.pow(10, 1 + (int) Math.log10(b)));

объяснение:

   1 + (int) Math.log10(b)     // number of digits (3 in case of 123)
   Math.pow(10, 1 + ... )      // 10...0 - 1 with required number of zeroes
 Giulio Paci03 июн. 2016 г., 19:09
@ Томас: Лично мне не нравится подход разбора строк. Первоначально я написал ответ, который был очень близок к этому, но удален, потому что этот был более полным. Я предложил добавить это уведомление к этому ответу, потому что оно мое любимое, но на самом деле его следует добавить к любому действительному ответу на этот вопрос.
 Dmitry Bychenko03 июн. 2016 г., 16:43
@Tom: спасибо! Конечно должно бытьc = a + ...
 Giulio Paci03 июн. 2016 г., 16:54
Я также хотел бы добавить примечание о том, что невозможно достичь идеальных результатов даже для некоторыхпростые значения, Другие проблемные случаи: подписанный int, очень большой int.
 Thomas03 июн. 2016 г., 17:30
Еще более быстрый подход может заключаться в том, чтобы просто использовать цикл и делитьb на 10, пока не станет меньше 1.
 Thomas03 июн. 2016 г., 17:19
Хотя этот подход может страдать от некоторых проблем точности, которых нет в подходе синтаксического анализа строк (по крайней мере, не в той же степени), и его сложнее читать, он является более быстрым подходом и, таким образом, может быть предпочтительным, если производительность является проблемой.
 Thomas03 июн. 2016 г., 17:33
@GiulioPaci, даже подход разбора строк пострадает от этих случаев (попробуйте разбор"1.-2"). Отрицательные числа всегда являются проблемой и не должны допускаться здесь, а проблемы точности с очень большими числами могут быть решены с помощьюBigDecimal (хотя вы тогда не сможете использоватьMath.log10() так далее.).

integerзатем соедините строки вместе, вставив "." между двумя. Затем преобразовать полученнуюstring кdouble.

Ваш ответ на вопрос