Как напечатать двойное значение без научной нотации с использованием Java?
Я хочу напечатать двойное значение в Java без показательной формы.
double dexp = 12345678;
System.out.println("dexp: "+dexp);
Это показывает это обозначение E: 1.2345678E7
,
Я хочу напечатать это так: 12345678
Каков наилучший способ предотвратить это?
18 ответов
Вы могли бы использовать printf()
с %f
:
double dexp = 12345678;
System.out.printf("dexp: %f\n", dexp);
Это напечатает dexp: 12345678.000000
, Если вы не хотите дробную часть, используйте
System.out.printf("dexp: %.0f\n", dexp);
При этом используется язык спецификатора формата, описанный в документации.
По умолчанию toString()
формат, используемый в исходном коде, изложен здесь.
Java предотвращает E запись в двойном:
Пять различных способов конвертировать двойное в нормальное число:
import java.math.BigDecimal;
import java.text.DecimalFormat;
public class Runner {
public static void main(String[] args) {
double myvalue = 0.00000021d;
//Option 1 Print bare double.
System.out.println(myvalue);
//Option2, use decimalFormat.
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(8);
System.out.println(df.format(myvalue));
//Option 3, use printf.
System.out.printf("%.9f", myvalue);
System.out.println();
//Option 4, convert toBigDecimal and ask for toPlainString().
System.out.println(new BigDecimal(myvalue).toPlainString());
System.out.println();
//Option 5, String.format
System.out.println(String.format("%.12f", myvalue));
}
}
Эта программа печатает:
2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000
Которые имеют все одинаковое значение.
Подсказка: если вы не уверены, почему эти случайные цифры появляются за определенным пороговым значением в двойном значении, это видео объясняет: computerphile, почему 0.1
+0.2
равный 0.30000000000001
?
Короче:
Если вы хотите избавиться от конечных нулей и проблем локали, то вам следует использовать:
double myValue = 0.00000021d;
DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS
System.out.println(df.format(myValue)); // Output: 0.00000021
Объяснение:
Почему другие ответы меня не устраивают:
Double.toString()
или жеSystem.out.println
или жеFloatingDecimal.toJavaFormatString
использует научные обозначения, если double меньше 10^-3 или больше или равно 10^7Используя
%f
десятичная точность по умолчанию равна 6, в противном случае вы можете жестко закодировать ее, но это приведет к добавлению дополнительных нулей, если у вас меньше десятичных знаков. Пример:double myValue = 0.00000021d; String.format("%.12f", myvalue); // Output: 0.000000210000
Используя
setMaximumFractionDigits(0);
или же%.0f
Вы удаляете любую десятичную точность, которая подходит для целых / длинных, но не для двойной:double myValue = 0.00000021d; System.out.println(String.format("%.0f", myvalue)); // Output: 0 DecimalFormat df = new DecimalFormat("0"); System.out.println(df.format(myValue)); // Output: 0
Используя DecimalFormat, вы локально зависимы. Во французском языке десятичный разделитель - это запятая, а не точка:
double myValue = 0.00000021d; DecimalFormat df = new DecimalFormat("0"); df.setMaximumFractionDigits(340); System.out.println(df.format(myvalue)); // Output: 0,00000021
Использование английского языка гарантирует, что вы получите точку для десятичного разделителя, где бы ни работала ваша программа.
Зачем использовать 340 тогда для setMaximumFractionDigits
?
Две причины:
setMaximumFractionDigits
принимает целое число, но его реализация имеет максимально допустимые цифрыDecimalFormat.DOUBLE_FRACTION_DIGITS
что равно 340Double.MIN_VALUE = 4.9E-324
так что с 340 цифрами вы точно не округлите свой двойник и не потеряете точность.
У меня есть другое решение, включающее toDlainString() BigDecimal, но на этот раз с использованием String-конструктор, который рекомендуется в javadoc:
этот конструктор совместим со значениями, возвращаемыми Float.toString и Double.toString. Как правило, это предпочтительный способ преобразования числа с плавающей запятой или двойного в BigDecimal, поскольку он не страдает от непредсказуемости конструктора BigDecimal (double).
В кратчайшей форме это выглядит так:
return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();
До Java 8 это приводит к значению "0.0" для любых двойных чисел с нулевым значением, поэтому вам необходимо добавить:
if (myDouble.doubleValue() == 0)
return "0";
NaN и бесконечные значения должны быть проверены дополнительно.
Окончательный результат всех этих соображений:
public static String doubleToString(Double d) {
if (d == null)
return null;
if (d.isNaN() || d.isInfinite())
return d.toString();
// Pre Java 8, a value of 0 would yield "0.0" below
if (d.doubleValue() == 0)
return "0";
return new BigDecimal(d.toString()).stripTrailingZeros().toPlainString();
}
Это также может быть скопировано / вставлено для работы с Float.
Вы можете попробовать это с DecimalFormat
, С этим классом вы очень легко разбираете свои числа.
Вы можете точно установить шаблон, который вы хотите использовать.
В вашем случае, например:
double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678
Компилятор Java/Kotlin преобразует любое значение больше 9999999 (больше или равно 10 миллионам) в научную нотацию, т.е. Epsilion обозначение.
Например: 12345678 преобразуется в 1.2345678E7
Используйте этот код, чтобы избежать автоматического преобразования в научную нотацию:
fun setTotalSalesValue(String total) {
var valueWithoutEpsilon = total.toBigDecimal()
/* Set the converted value to your android view using setText() function */
totalSalesValue.setText() = valueWithoutEpsilon.toPlainString()
}
Это будет работать до тех пор, пока ваш номер является целым числом:
double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);
Если переменная типа double имеет точность после десятичной точки, она ее усекает.
Мне нужно было конвертировать некоторые двойные значения в валюты и я обнаружил, что большинство решений были в порядке, но не для меня.
DecimalFormat
в конечном итоге был путь для меня, вот что я сделал:
public String foo(double value) //Got here 6.743240136E7 or something..
{
DecimalFormat formatter;
if(value - (int)value > 0.0)
formatter = new DecimalFormat("0.00"); // Here you can also deal with rounding if you wish..
else
formatter = new DecimalFormat("0");
return formatter.format(value);
}
Как видите, если число натуральное, я получаю, скажем, 20000000 вместо 2E7 (и т. Д.) - без десятичной точки.
И если это десятичное число, я получаю только две десятичные цифры.
Следующий код определяет, представлен ли указанный номер в научной записи. Если это так, то он представлен в обычном формате с максимумом "25" цифр.
static String convertFromScientificNotation(double number) {
// Check if in scientific notation
if (String.valueOf(number).toLowerCase().contains("e")) {
System.out.println("The scientific notation number'"
+ number
+ "' detected, it will be converted to normal representation with 25 maximum fraction digits.");
NumberFormat formatter = new DecimalFormat();
formatter.setMaximumFractionDigits(25);
return formatter.format(number);
} else
return String.valueOf(number);
}
Я думаю, что у всех была правильная идея, но все ответы были не простыми. Я вижу, что это очень полезный кусок кода. Вот фрагмент того, что будет работать:
System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));
".8"
где вы указываете количество десятичных знаков, которые вы хотели бы показать.
Я использую Eclipse, и это не сработало.
Надеюсь, это было полезно. Буду признателен за любые отзывы!
Это будет работать не только для целых чисел:
double dexp = 12345678.12345678;
BigDecimal bigDecimal = new BigDecimal(Double.toString(dexp));
System.out.println("dexp: "+ bigDecimal.toPlainString());
Это может быть касательной.... но если вам нужно поместить числовое значение в виде целого числа (которое слишком велико для целого числа) в сериализатор (JSON и т. Д.), Тогда вам, вероятно, понадобится "BigInterger"
Пример:
значение - строка - 7515904334
Нам нужно представить это как число в сообщении Json:
{
"contact_phone":"800220-3333",
"servicer_id":7515904334,
"servicer_name":"SOME CORPORATION"
}
Мы не можем его распечатать, иначе получим следующее:
{
"contact_phone":"800220-3333",
"servicer_id":"7515904334",
"servicer_name":"SOME CORPORATION"
}
Добавление значения к узлу таким образом дает желаемый результат:
BigInteger.valueOf(Long.parseLong(value, 10))
Я не уверен, что это действительно по теме, но поскольку этот вопрос был моим самым популярным, когда я искал свое решение, я подумал, что поделюсь здесь для блага других, лгите мне, кто плохо ищет.:D
использовать
String.format ("%.0f", number)
% .0f для нулевого десятичного числа
String numSring = String.format ("%.0f", firstNumber);
System.out.println(numString);
У меня была такая же проблема в моем производственном коде, когда я использовал его в качестве строкового ввода для функции math.Eval(), которая принимает строку типа "x + 20 / 50"
Я просмотрел сотни статей... В конце концов, я пошел с этим из-за скорости. И поскольку функция Eval собиралась преобразовать его обратно в свой собственный числовой формат, в конце концов, и math.Eval() не поддерживал завершающий E-07, который возвращали другие методы, и что-либо более 5 dp было слишком много деталей для моего приложения в любом случае,
Это теперь используется в производственном коде для приложения, которое имеет более 1000 пользователей...
double value = 0.0002111d;
String s = Double.toString(((int)(value * 100000.0d))/100000.0d); // Round to 5 dp
s display as: 0.00021
Это работает для меня. На выходе будет строка.
String.format("%.12f", myvalue);
Мое решение: String str = String.format ("%.0f", yourDouble);
Для целочисленных значений, представленных double
Вы можете использовать этот код, который намного быстрее, чем другие решения.
public static String doubleToString(final double d) {
// check for integer, also see https://stackru.com/a/9898613/868941 and
// https://github.com/google/guava/blob/master/guava/src/com/google/common/math/DoubleMath.java
if (isMathematicalInteger(d)) {
return Long.toString((long)d);
} else {
// or use any of the solutions provided by others
return Double.toString(d);
}
}
// Java 8+
public static boolean isMathematicalInteger(final double d) {
return StrictMath.rint(d) == d && Double.isFinite(d);
}
Хороший способ преобразовать научную электронную нотацию
String.valueOf(YourDoubleValue.longValue())