Move decimal point in double - java

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());

Related

Returning a double value but with a trailing zero at the end

Double d = 10.30
When I use this value of d i.e 10.30 it becomes 10.3
Is there anyway that I can sustain this value of 10.30
Remember I cannot change the data-type it should be a double
Is there a way??
You can't do this with Double class.
If you want to display a value with zero you could do this:
System.out.printf("%.2f%n", d);
It means that your variable d will be displayed with 2 digits after point. So, if d = 10.3, the code above will show 10.30
String also can store formatted value:
String s = String.format("%.2f%n", d);
System.out.println(s);
A double only contains only information about the value it represents, but not about the precision of it.
Whether a double is represented as 10.3, 10.30, 10.300000 etc. is determined by the display resp. string conversion routine, not by the routine which generates the value.
The best solution is
private static final DecimalFormat df = new DecimalFormat("0.00");
df.format(amountDouble)

How to remove decimal in java without removing the remaining digits

Is there any method to remove the . in java into a double value?
Example :
56.11124
to
5611124
I don't think there's a mathematical way to find out how many decimals there are in a double. You can convert to a String, replace the dot, and then convert it back:
Double.parseDouble(Double.toString(56.11124).replace(".", ""));
Be careful of overflows when you parse the result though!
Here's one way to do it,
First, convert the double to a string. Then, call replace to replace . with an empty string. After that, parse the result into an int:
double d = 5.1;
String doubleString = Double.toString(5.1);
String removedDot = doubleString.replace(".", "");
int result = Integer.parseInt(removedDot);
Obviously, this wouldn't work if the double's string representation is in scientific notation like 5e16. This also does not work on integral double values, like 5, as its string representation is 5.0.
doubles are inaccurate by nature. 5 and 5.0 are the same value. This is why you can't really do this kind of operation. Do you expect different results for a and b?
double a = 5;
double b = 5.0;
If you do, then you can't really do this, since there is no way of knowing what the programmer wrote exactly at runtime.
This might work
class Example {
public static void main(String[] args) {
double val = 56.1112;
while( (double)((int)val) != val )
{
val *= 10;
}
System.out.printf( "%.0f", val );
}
}
Output: 561112
This works by casting the double to int which truncates the floating information 56.11124 => 56. While the values aren't equal you multiply it by the base to push the . out. I don't know if this is the best way.
You can convert to BigDecimal and use the unscaledValue method:
BigInteger unscaled = new BigDecimal(myDouble).unscaledValue();
Depending on your intended output, you might also use BigDecimal#valueof(double) to create the intermediate BigDecimal.
Javadoc for BigDecimal#new(double)
Javadoc for BigDecimal#valueOf(double)
Javadoc for BigDecimal#unscaledValue()
You can convert it to a String and remove the . and convert it back to double something like
double value = 56.11124;
value = Double.valueOf(("" + value).replace(".", "")).doubleValue();
This will return 5611124.0 since its a double you will have the floating point. You can convert it to an int, but you have to take care of the possible overflow. Otherwise it would look like this
int normalized = (int) value;

How to convert the 6020494385.89982 string value to double

How to convert the "6020494385.89982" string value to a double?
String ss = "6020494385.89982";
double dd = Double.parseDouble(String.valueOf(ss));
System.out.println(dd);
I am getting the output as
6.02049438589982E9 but I want 6020494385.89982 as double value.
Use of a DecimalFormatobject should do the trick
String ss = "6020494385.89982";
double dd = Double.parseDouble(String.valueOf(ss));
System.out.println(new DecimalFormat("#0.00000").format(dd));
Or you can use System.out#printf()
System.out.printf("%.5f", dd);
Because System.out.println has a particular way of working with double precisions that will not work in this particular case for example.
The number is correct. 6.02049438589982E9 is just the scientific notation, which is the default when you print a double. If you want the non-scientific notation, you could just use printf instead of println:
System.out.printf("%f\n", dd);
6.02049438589982E9 is the same as 6020494385.89982
6.02049438589982E9 = 6.02049438589982 X 10^9
the value stored in the double is 6020494385.89982 However, when you print it out, it represents in this format: 6.02049438589982E9
You do not need to convert into double if in the end you want the representation in the same format as the current value of ss variable.
However if you need to convert for some other purpose and then need to show in that format later/else where you can use DecimalFormat as others have suggested.

BigDecimal methods send formatted numbers

I'm trying to round my big BigDecimals off to three decimal places. For instance, let's say I have some
BigDecimal X = 1362.59633
I wanna get:
1362.596
Here is what I'm doing:
BigDecimal Y = X.round(new MathContext(3));
But I keep getting this: 1.36E+3.
What should I do in this case?
Thanks
You actually don't have to round but you have to set the scale of your BigDecimal:
BigDecimal X = new BigDecimal("1362.59633");
X = X.setScale(3, BigDecimal.ROUND_HALF_UP);
System.out.println(X.doubleValue());
This will print out 1362.596.
Note that setScale returns a new BigDecimal so you have to assign it like I did in my example.
edit: there are several kinds of rounding strategies. Check the BigDecimal class for reference. I edited my answer to use BigDecimal.ROUND_HALF_UP.
BigDecimal X = new BigDecimal(1362.59633);
X = X.setScale(3,RoundingMode.HALF_EVEN);
System.out.println(X); //1362.596
Note that since BigDecimal objects are immutable, calls of this method
do not result in the original object being modified, contrary to the
usual convention of having methods named setX mutate field X. Instead,
setScale returns an object with the proper scale; the returned object
may or may not be newly allocated.
BigDecimal y= x.round(new MathContext(7, RoundingMode.HALF_EVEN));
This should work for you.
If you use only double you can do
double d = 1362.59633;
double d2 = Math.round(d * 1e3) / 1e3;
System.out.println(d2);
prints
1362.596
Note: this doesn't create any objects to perform the rounding.
We can use DecimalFormat class to define the format of the double data. You can define like new DecimalFormat("####.000")
we can call format method the value you want.
Example
DecimalFormat format = new DecimalFormat("####.000");
format.format("1362.59633");
First set the scale to 3 using setScale with RoundingMode.DOWN as the rounding mode to truncate
Then call toPlainString to guarantee the return of a String representation without an exponent field
Calling toString on a BigDecimal does not guarantee the return of a String without an exponent. It returns the string representation using scientific notation if an exponent is needed
An example based on your question:
BigDecimal x = BigDecimal.valueOf( 1362.59633 );
System.out.println( x.setScale( 3, RoundingMode.DOWN ).toPlainString( ) );

Converting numeric value with currency symbol back to Decimal with NumberFormat

I would like to convert a possibly Decimal value prefixed with currency symbol into only numeric value.
For example -
The value can be like any of the following
String s1 = "£32,847,676.65";
String s2 = "£3,456.00";
String s3 = "£831,209";
I would like the result after conversion to be like - 32847676.65, 3456.00 and 831209.
I tried using the parse() method of the NumberFormat in this way -
NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.UK);
numberFormat.setMinimumFractionDigits(2);
Number num = nf.parse(s1);
double dd = num.doubleValue();
BigDecimal gg = new BigDecimal(dd);
System.out.println(gg);
But the result is - 32847676.649999998509883880615234375 which is not quite exactly the correct one.
I need it to be numeric so that may be I can perform some kind of calculation.
Can you guys guide me with what else can I try
You already parse the value correctly. The problem is this:
BigDecimal gg = new BigDecimal(dd);
You covnert the value to BigDecimal, and the rounding problems of doubles account for the decimal places after the dot. Use:
BigDecimal gg = new BigDecimal(dd).setScale(2);
or
BigDecimal gg = new BigDecimal(dd).setScale(2,RoundingMode.HALF_UP);
When playing with BigDecimal, the appropriate constructor is BigDecimal(String val)
NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.UK);
BigDecimal gg = new BigDecimal(nf.parse(s1).toString());
System.out.println(gg);
BigDecimal(double val) does construct an exact decimal representation of the double value, which is not the human readable value you expected.
"The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
[...]
Therefore, it is generally recommended that the String constructor be used in preference to this one"
Source : BigDecimal javadoc
You can try the following without BigDecimal or NumberFormat. ;)
String s1 = "£32,847,676.65";
// remove the £ and ,
String s2 = s1.replaceAll("[£,]", "");
// then turn into a double
double d = Double.parseDouble(s2);
// and round up to two decimal places.
double value = (long) (d * 100 + 0.5) / 100.0;
System.out.printf("%.2f%n", value);
prints
32847676.65
If youw ant to avoid rounding error in your calculations but don't want the heavy weight BigDecimal you can use long cents.
// value in cents as an integer.
long value = (long) (d * 100 + 0.5);
// perform some calculations on value here
System.out.printf("%.2f%n", value / 100.0);
It is not guaranteed to work, but according to the NumberFormat API documentation, its getXyzInstance methods will return a DecimalFormat instance for "the vast majority of locales". This can probably be interpreted as "for all locales, unless proprietary locale service providers are installed".
If you can cast your NumberFormat to DecimalFormat, you can tell it to parse to a BigDecimal directly, reducing your code to:
DecimalFormat nf = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.UK);
nf.setParseBigDecimal(true);
BigDecimal gg = (BigDecimal) nf.parse(s1);
System.out.println(gg);
In this case, you will have no problem with the inaccuracy of binary floating point numbers.

Categories

Resources