Converting a String that contains decimal to Long - java

I have following sample (link to ideone).
long lDurationMillis = 0;
lDurationMillis = Long.parseLong("30000.1");
System.out.print("Play Duration:" + lDurationMillis);
It throws an exception:
Exception in thread "main" java.lang.NumberFormatException: For input string: "30000.1"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Long.parseLong(Long.java:419)
at java.lang.Long.parseLong(Long.java:468)
at Main.main(Main.java:9)
But why it wont let me convert that number to a string directly ?I can convert number to integer and than convert to double . But is there any other way ?

The value 30000.1 is an invalid long value. You could parse the double value first:
lDurationMillis = (long)Double.parseDouble("30000.1");

You could use BigDecimal in this case:
BigDecimal bd = new BigDecimal("30000.1");
long l = bd.setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
System.out.println(l);

The title says converting string to long, first question is about coverting number to string, next statement about converting number to integer to string. I am confuse.
But for anything to do with floating points, I have to point you at obligatory reference What Every Computer Scientist Should Know About Floating-Point Arithmetic .
In java, int and long do not have fractional parts, so a string like 3000.1 cannot be covnerted to one of these. It can be converted to float or double but if you read the above article you will realize that the coversion can be lossy, i.e. if you canvert that double back to a String you may not get the original 3000.1 back. It will be something close, for appropriate defintion of close, but may not be same.
If you want to use exact precision then BigDecimal is your friend. It will be much slower then the number types, but it will be precise.

Because long can't have fractional part, you could convert it to double and then cast it to long ignoring fractional part

You can do NumberFormat handling as below :
long lDurationMillis = 0;
try{
NumberFormat nf = NumberFormat.getInstance();
lDurationMillis = nf.parse("30000.1").longValue();
System.out.print("Play Duration:" + lDurationMillis);
}catch(ParseException e)
{
e.printStackTrace();
}
Output:
Play Duration:30000

Related

when converting power to number the number formatting is not good

I have got some troubles with conversion, but the following code converts right sometime and sometime wrong
double d = Double.parseDouble(results.get(position)); // Also accepts format like "1.574e10"
Log.e("test",String.valueOf(d));
String s1= String.format("%f",d);
Log.e("test",s1);
This is example for conversion didn't work
08-28 12:15:53.679: E/test(22754): 1.4910315055357396E-9
08-28 12:15:53.679: E/test(22754): 0,000000
The problem is that your double is very small and %f prints only 6 numbers after the decimal point by default.
Instead use:
String s1 = String.format("%.10f", d);
The correct way to format a double to a string would be:
String.format("%1$,.4f", myDouble)
The above example gives you an accuracy of 4 decimal places. Another way to format a double would be with DecimalFormat:
DecimalFormat df = new DecimalFormat("#.##");
String number = df.format(543.235555);

Move decimal point in double

I have this code:
Long dval = new Long((new Date()).getTime());
System.out.println("ogval:"+dval);
Double dd = (double)dval;
System.out.println("dval:"+dd);
Here is the output:
ogval:1381490769636
dval:1.381490769636E12
When I convert the value to Double, it adds a decimal point. Can I do the typecasting and get the value in double as it is?
The desired output would be:
ogval:1381490769636
dval:1381490769636
I have a function whose argument accepts only double value. When I try to pass a timestamp, it passes the decimal value inside the method.
I can't edit the function because its an inbuilt function of some package.
Simple answer is no.
Floating types can contain integer up to some arbitrary value, given by the way floats are stored. If the number is too big, it gets converted to decimal.
If you need to work with big integer values use BigInteger class.
Great tool to examine those imperfections is this float converter.
Try 123456789 in the float converter, it won't be stored exactly.
Use DecimalFormat, like:
Long dval = new Long((new Date()).getTime());
System.out.println("ogval:" + dval);
Double dd = (double) dval;
DecimalFormat format=new DecimalFormat("##########");
System.out.println("dval:" + format.format(dd));
Your problem is not with the type that you are using, but with the format that you are applying to it. Currently, the default format is used, because string + double implicitly calls Double.toString, which converts your specific double to a String using scientific notation. You can force a different format if you wish by using printf or any other formatting method that Java makes available to you:
System.out.printf("dval: %12.0f", dd);
(demo)
as an alternative you can try using bigdecimal
Long dval = new Long((new Date()).getTime());
System.out.println("ogval:"+dval);
Double dd = (double)dval;
System.out.println("dval:"+dd);
BigDecimal bd = new BigDecimal(dval);
System.out.println("bdval:"+bd.toPlainString());

Java convert string to number, floating point only when needed?

I want to conver a string to number in Java. I already tried with two methods but both work bad with integers, adding an unneeded floating point: "1" > 1.0 (when I want "1" > 1 and "1.5" > 1.5). I found a couple more ways to convert strings to numbers but they either don't work or are many lines long, I cannot believe it's so complicated coming from javascript where I only need parseFloat().
This is what I'm trying now:
String numString = "1".trim().replaceAll(",","");
float num = (Float.valueOf(numString)).floatValue(); // First try
Double num2 = Double.parseDouble(numString); // Second try
System.out.println(num + " - " + num2); // returns 1.0 - 1.0
How can I have the floating point only when needed?
To format a float as you wish, use DecimalFormat :
DecimalFormat df = new DecimalFormat("#.###");
System.out.println(df.format(1.0f)); // prints 1
System.out.println(df.format(1.5f)); // prints 1.5
In your case, you could use
System.out.println(df.format(num) + " - " + df.format(num2));
I think what you're looking for is DecimalFormat
DecimalFormat format = new DecimalFormat("#.##");
double doubleFromTextField = Double.parseDouble(myField.getText());
System.out.println(format.format(doubleFromTextField));
The problem is with your question really in a type-safe language and I think you are mixing conversion and string representation. In Java or C# or C++ you convert to some predictable/expected type, looks like you expect the "Variant" behavior that you are used to in JavaScript.
What you could do in a type-safe language is this:
public static Object convert(String val)
{
// try to convert to int and if u could then return Integer
ELSE
//try to convert to float and if you could then return it
ELSE
//try to convert to double
etc...
}
Of course this is very inefficient just like JavaScript is compared to C++ or Java. Variants/polymorphism (using Object) comes at cost
Then you could do toString() to get integer formatted as integer, float as float and double as double polymorphically. But your question is ambiguous at best that leads me to believe that there is conceptual problem.

Convert String (representing decimal number) to long

I've googled around a bit but could not find examples to find a solution. Here is my problem:
String s = "100.000";
long l = Long.parseLong(s);
The 2nd line of code which tries to parse the string 's' into a long throws a NumberFormatException.
Is there a way around this? the problem is the string representing the decimal number is actually time in milliseconds so I cannot cast it to int because I lose precision.
You could use a BigDecimal to handle the double parsing (without the risk of precision loss that you might get with Double.parseDouble()):
BigDecimal bd = new BigDecimal(s);
long value = bd.longValue();
as i don't know is your 100.000 equals 100 or 100 000
i think safest solution which i can recommend you will be:
NumberFormat nf = NumberFormat.getInstance();
Number number = nf.parse("100.000");
long l = number.longValue();
'long' is an integer type, so the String parse is rejected due to the decimal point. Selecting a more appropriate type may help, such as a double.
Just remove all spaceholders for the thousands, the dot...
s.replaceAll(".","");
You should use NumberFormat to parse the values
We can use regular expression to trim out the decimal part. Then use parseLong
Long.parseLong( data.replaceAll("\..*", ""));
If you don't want to loose presision then you should use multiplication
BigDecimal bigDecimal = new BigDecimal("100.111");
long l = (long) (bigDecimal.doubleValue() * 1000);<--Multiply by 1000 as it
is miliseconds
System.out.println(l);
Output:
100111

Detect Java NumberFormat inaccuracy

I want to parse an integer accurately, one that has been potentially formatted according to the current locale. If I didn't parse the integer accurately, I want to know it. So I use:
String string = "1111122222333334444455555";
Locale locale = Locale.getDefault();
NumberFormat numberFormat = NumberFormat.getIntegerInstance(locale);
numberFormat.setParseIntegerOnly();
Number number = numberFormat.parse(string);
Obviously "1111122222333334444455555" represents a big number, bigger than a Long can handle. So NumberFormat gives me... a Double??
I guess I would have expected to receive a BigInteger rather than a Double, especially since I asked for an integer-specific number formatter. But never mind that; the bigger problem is that the double value I get back is 1.1111222223333344E24! This is not equal to 1111122222333334444455555!!
If NumberFormat gives me a parsed value that does not equal that stored in the input string, how do I detect that?
Put another way: "How can I know if the Double value I get back from NumberFormat is exactly equivalent to the integral value represented in the original string?"
The javadocs for parse() state that it will return a Long if possible, otherwise it will return a Double. So just check that the return value is a Long.
"Returns a Long if possible (e.g., within the range [Long.MIN_VALUE, Long.MAX_VALUE] and with no decimals), otherwise a Double."
"How can I know if the Double value I get back from NumberFormat is exactly equivalent to the integral value represented in the original string?"
If it returns a Double, then it is not exactly equivalent to your integral value because a Double cannot accurately represent values at that magnitude. Concrete example:
Number a = numberFormat.parse("-9223372036854775809"); // Integer.MIN_VALUE - 1
Number b = numberFormat.parse("-9223372036854775810"); // Integer.MIN_VALUE - 2
System.out.println((a.equals(b))); // prints "true"
Number c = numberFormat.parse("-9223372036854776800");
System.out.println((a.equals(c))); // prints "true"
For you question -
If NumberFormat gives me a parsed value that does not equal that stored in the input string, how do I detect that?
You can use
if(number.toString().equals(string))
//Parsed correctly
else
//Invalid parse
This might not be the solution but worth notice.
public static void main(String[] args) {
String string = "1111122222333334444455555";
Locale locale = Locale.getDefault();
NumberFormat numberFormat = NumberFormat.getIntegerInstance(locale);
numberFormat.setParseIntegerOnly(true);
Number number = numberFormat.parse(string);
BigDecimal b = new BigDecimal(number.toString());
System.out.println(b.toBigInteger());
}
Output of this code is : 1111122222333334400000000
As you can see this is not equal to the number in the actual string , so their might be an overflow occoured.

Categories

Resources