scientific - quitar notacion cientifica javascript
¿Cómo imprimo un valor doble sin notación científica usando Java? (12)
Quiero imprimir un valor doble en Java sin forma exponencial.
double dexp = 12345678;
System.out.println("dexp: "+dexp);
Muestra esta notación E: 1.2345678E7
.
Quiero que lo imprima así: 12345678
¿Cuál es la mejor manera de prevenir esto?
Java evita la notación E en un doble:
Cinco formas diferentes de convertir un doble en un número normal:
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));
}
}
Este programa imprime:
2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000
Que son todos del mismo valor
Protip: si no está seguro de por qué esos dígitos aleatorios aparecen más allá de un cierto umbral en el valor doble, este video explica: Computerphile ¿por qué 0.1
+ 0.2
igual a 0.30000000000001
?
Creo que todos tuvieron la idea correcta, pero todas las respuestas no fueron directas. Puedo ver que esto es una pieza de código muy útil. Aquí hay un fragmento de lo que funcionará:
System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));
el ".8"
es donde establece la cantidad de decimales que desea mostrar.
Estoy usando Eclipse y no funcionó.
Espero que esto haya sido útil. ¡Le agradecería cualquier comentario!
El compilador Java / Kotlin convierte cualquier valor superior a 9999999 (mayor o igual a 10 millones) en notación científica, es decir. Notación de Epsilion.
Ej: 12345678 se convierte a 1.2345678E7
Use este código para evitar la conversión automática a notación científica:
fun setTotalSalesValue(String total) {
var valueWithoutEpsilon = total.toBigDecimal()
/* Set the converted value to your android view using setText() function */
totalSalesValue.setText() = valueWithoutEpsilon.toPlainString()
}
El siguiente código detecta si el número proporcionado se presenta en notación científica. Si es así, se representa en una presentación normal con un máximo de ''25'' dígitos.
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);
}
Esto funcionará siempre que su número sea un número entero:
double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);
Si la variable doble tiene precisión después del punto decimal, la truncará.
Necesitaba convertir algunos valores de doble a moneda y descubrí que la mayoría de las soluciones estaban bien, pero no para mí.
El DecimalFormat
finalmente fue el camino para mí, así que esto es lo que hice:
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);
}
Como puede ver, si el número es natural, obtengo - digamos - 20000000 en lugar de 2E7 (etc.) - sin ningún punto decimal.
Y si es decimal, obtengo solo dos dígitos decimales.
Para valores enteros representados por un double
, puede usar este código, que es mucho más rápido que las otras soluciones.
public static String doubleToString(final double d) {
// check for integer, also see https://.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);
}
Puede usar printf()
con %f
:
double dexp = 12345678;
System.out.printf("dexp: %f/n", dexp);
Esto imprimirá dexp: 12345678.000000
. Si no quieres la parte fraccionaria, usa
System.out.printf("dexp: %.0f/n", dexp);
Utiliza el lenguaje de especificador de formato explicado en la documentation .
El formato predeterminado toString()
utilizado en su código original se explica here .
Puedes probarlo con DecimalFormat
. Con esta clase eres muy flexible al analizar tus números.
Puede establecer exactamente el patrón que desea usar.
En tu caso, por ejemplo:
double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678
Tengo otra solución que involucra a BigDecimal''s toPlainString (), pero esta vez usando el String-constructor, que se recomienda en el javadoc:
este constructor es compatible con los valores devueltos por Float.toString y Double.toString. Esta es generalmente la forma preferida de convertir un flotante o doble en un BigDecimal, ya que no adolece de la imprevisibilidad del constructor BigDecimal (doble).
Se ve así en su forma más breve:
return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();
Pre Java 8, esto da como resultado "0.0" para cualquier Dobles de valor cero, por lo que necesitaría agregar:
if (myDouble.doubleValue() == 0)
return "0";
NaN e infinitos valores tienen que comprobarse extra.
El resultado final de todas estas consideraciones:
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();
}
Esto también se puede copiar / pegar para que funcione bien con Float.
Tuve el mismo problema en mi código de producción cuando lo estaba usando como entrada de cadena a una función math.Eval () que toma una cadena como "x + 20/50"
Miré cientos de artículos ... Al final fui con esto debido a la velocidad. Y porque la función Eval iba a convertirlo de nuevo en su propio formato numérico y eventualmente math.Eval () no admitía el E-07 final que devolvieron otros métodos, y cualquier valor superior a 5 dp era demasiado detallado para mi aplicación de todos modos .
Esto ahora se usa en el código de producción para una aplicación que tiene más de 1,000 usuarios ...
double value = 0.0002111d;
String s = Double.toString(((int)(value * 100000.0d))/100000.0d); // Round to 5 dp
s display as: 0.00021
En breve:
Si desea deshacerse de los ceros finales y los problemas de configuración regional, entonces debe usar:
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
Explicación:
Por qué otras respuestas no me sentaron bien:
-
Double.toString()
oSystem.out.println
oFloatingDecimal.toJavaFormatString
utiliza notaciones científicas si double es menor que 10 ^ -3 o mayor o igual que 10 ^ 7 Al usar
%f
, la precisión decimal predeterminada es 6, de lo contrario puede codificarla, pero resulta en cero adicionales si tiene menos decimales. Ejemplo:double myValue = 0.00000021d; String.format("%.12f", myvalue); // Output: 0.000000210000
Mediante el uso de
setMaximumFractionDigits(0);
o%.0f
quita cualquier precisión decimal, lo cual está bien para números enteros / largos, pero no para el doble: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
Al usar DecimalFormat, usted es dependiente local. En la configuración regional francesa, el separador decimal es una coma, no un punto:
double myValue = 0.00000021d; DecimalFormat df = new DecimalFormat("0"); df.setMaximumFractionDigits(340); System.out.println(df.format(myvalue)); // Output: 0,00000021
Al utilizar la configuración regional INGLÉS, se asegura de obtener un punto para el separador decimal, donde quiera que se ejecute su programa.
¿Por qué usar 340 entonces para setMaximumFractionDigits
?
Dos razones:
-
setMaximumFractionDigits
acepta un entero, pero su implementación tiene un máximo de dígitos permitidos enDecimalFormat.DOUBLE_FRACTION_DIGITS
que equivale a 340 -
Double.MIN_VALUE = 4.9E-324
por lo que con 340 dígitos está seguro de no redondear su doble y perder precisión.