BigDecimal math operations - java

I want to write this in Java but I get some errors and I am not sure how to write it:
C = A - (A*B)/100
All of my values are defined as Bigdecimal objects.
I tried something like this but is not working:
C = A.subtract(A.multiply(B).divide(100));
..I get a warning to add more arguments to the divide method. I do not know how to write it correctly. What am I doing wrong? Thanks in advance

BigDecimal has no divide(int) method, but that's what you're asking it to do with .divide(100), because 100 is an int literal. If you refer to the documentation, all of the divide methods accept BigDecimal instances.
You can use divide(BigDecimal) instead, by using BigDecimal.valueOf:
C = A.subtract(A.multiply(B).divide(BigDecimal.valueOf(100)));
(It accepts a long [or double], but int can be promoted to long.)
Alternately, for some values, you might use the String constructor instead:
C = A.subtract(A.multiply(B).divide(new BigDecimal("100")));
...particularly if you're dealing with floating-point values that might lose precision in double. 100 is fine for valueOf, though.

c = a.subtract(a.multiply(b).divide(BigDecimal.valueOf(100.0)));

Related

Efficient way to convert long to String in Java

I've been using
long a = 123456789;
String b = a+"";
to convert a long value (or int) to String, or in this perspective, treat it as String. My question is, is it ok to do this? Are there any negative impact?
And is there any difference in using String.valueOf() vs Long.toString()?
Thanks
It is ok to do this as recent JVM will likely reduce it to:
String b = String.valueOf(a);
As for negatives, it is not good Java coding style as there is ambiguity. If a was null, would b = "null"? or will an NPE be thrown? You know the answer with experience, but this should be obvious to all readers of your code.
First, your code doesn't compile - you have to append an L after the literal:
Long a = 123456789L;
String.valueOf() and Long.toString() methods both have a primitive long as a parameter, but since a is an wrapper (Long), you can just use the Object#toString() method:
String b = a.toString();
If a, however, is a primitive (long), both String.valueOf() and Long.toString() will do the same, so it's a matter of preference which one to use.

BigDecimal precision above 1E22

for some reason I found myself coding some piece of software, that should be able to perfom some astronomic calculations.
While most of it will be about transfering the correct formula into Java, I found an annoying Problem right at the verry beginning of my "test how to calculate big numbers".
Well... Imagine the Sun (our Sun), which has a mass of (about and rounded, for more easy explaining) 10E30 kg. Ten with 30 following Zeros. All native datatypes are just unusuable for this. To mention: I KNOW that I could use 3000 to calculate things and just add trailing zeros in the output-view, but I hoped to keep it as precise as possible. So using short numbers will be my last resort only.
Comming to the Problem. Please have a look at the code:
BigDecimal combinedMass = new BigDecimal(1E22);
int massDistribution = 10;
Integer mD1 = massDistribution;
Integer mD2 = 100 - massDistribution;
BigDecimal starMass;
BigDecimal systemMass;
systemMass = combinedMass.divide(new BigDecimal("100")).multiply(new BigDecimal(mD1.toString()));
starMass = combinedMass.divide(new BigDecimal("100")).multiply(new BigDecimal(mD2.toString()));
System.out.println((systemMass).toEngineeringString());
System.out.println((starMass));
It will output 1000000000000000000000 and 9000000000000000000000, whats exactly what I did expect. But look at the combineMass Field. If I raise it to 1E23, the Output will change
I get 9999999999999999161139.20 and 89999999999999992450252.80...
So I know I could use jut BigInteger, because its more reliable in this case, but for the sake of precicion, sometimes the BigWhatEver may drop to something like 50.1258
Plus, I hope to get the 10.xE30 as output, whats only possible using bigDecimals.
I want to know: Is there no way avoidng this (that error appers above 1E23 for every value I tried), while keeping the ability to calculate Floating-Points? Should I cut the After-Decimal-Separator-Values for this Field to two digets?
And for something more to wonder about:
System.out.println(combinedMass.precision());
in relation with the code above will provide 23 for that case, but En+1 for most other values (Thats was when I grow really confused)
Thanks for advise.
You're using basic types without realizing it:
new BigDecimal(1E22);
Here, 1E22 is a primitive double, and you already lost precision by using it.
What you want is
new BigDecimal("10000000000000000000000");
or
new BigDecimal(10).pow(22);

How do I use ArrayList<Integer>#contains when I only have a BigInteger?

I am pulling data values from a database that returns a List of <Integer>. However, I would like to see if the List contains my BigInteger. Is there a simple way to do this?
I currently have the following code in Java:
ArrayList<Integer> arr = new ArrayList<Integer>() {{add(new Integer(29415));}};
boolean contains = arr.contains(29415); // true
boolean contains2 = arr.contains(new BigInteger("29415")); // false
I'm not sure on an efficient way to do this?
The correct answer will be returned by evaluation of the following:
val != null
&& BigInteger.valueOf(Integer.MIN_VALUE).compareTo(val) < 0
&& BigInteger.valueOf(Integer.MAX_VALUE).compareTo(val) > 0
&& list.contains(val.intValue())
This will correctly solve the question of whether the BigInteger you have is "contained" within the List<Integer>. Note that here we only downcast where necessary. If the val is outside the range of Integer values there is no need to downcast as we know that the value cannot be within the list.
A more relevant question is whether you should actually be using a List<BigInteger> in place of a List<Integer> but that is a different question and not part of the answer to your explicit question
While arshajii provides a solution which works, i would vote against it.
You should never downcast values. You are running in danger of your program producing larger values which translate to invalid values when downcasted. This kind of bug will be super nasty to troubleshoot months later.
If your code works with BigInteger, then you should convert all values from the database into BigInteger. This is an upcast where you cannot loose values.
Overall I would value correctness over efficiency. If at all, I would reconsider your usage of BigInteger (maybe long is fine?) but because you have it, I assume you have a reason for it.
In Java List.contains() uses the equals() method internally and because BigInteger.equals(Integer) returns false, your List.contains() also returns false. Either use the an List<BigInteger> or extract the Int value from BigInteger (as arshajii explained!). Of course, if you really want to search effectively, you should think of a binary search (in a sorted list) or of another data structure like Map.
You can try using BigInteger#intValue():
arr.contains(myBigInteger.intValue())
Note, however, that if myBigInteger is too big to fit into an int, then only the lower 32 bits will be returned (as described in the linked docs). Therefore, you might want to check if myBigInteger is less than or equal to Integer.MAX_VALUE before checking for containment.

not able to convert bigdecimal to string in java

Here is the java code
usageType = (String) c.getSrcValue("USAGETYPE");
c is a arraylist.
I populate it with this field from DB.
"USAGETYPE" NUMBER(*,0),
I get the following error
java.lang.ClassCastException: java.math.BigDecimal cannot be cast to String
Can you please help me out
Well, you cannot convert an object to a string by casting. Not in Java, in any case.
Try
usageType = c.getSrcValue("USAGETYPE").toString();
That is, if you actually need it as a string, which smells a little dubious in the first place. Usually the only place where numbers are needed as strings is the UI and you've got appropriate other places to do that conversion, normally (e.g. CellRenderers in Swing).
Simply write
usageType = c.getSrcValue("USAGETYPE").toString();
or
usageType = ""+c.getSrcValue("USAGETYPE");

BigDecimal assign operator

I have a problem with assigning one big decimal value to another
I am trying such as creating one temp big decimal and add 0 to another big decimal
BigDecimal temp = new BigDecimal(0);
dropStartValue = temp.add(newCounterValue);
However, I only want simply do the operation below on big decimals:
dropStartValue = newCounterValue
You haven't specified the type of either dropStartValue or newCounterValue. If they're both BigDecimals, then this should be fine:
dropStartValue = newCounterValue;
Note that although that's just making both variables refer to the same object, it's safe because BigDecimal itself is immutable.
If that's not working for you, please give details of what problems you're seeing (exceptions? compile-time errors?).
Assuming this is Java ans newCounterValue is an integer type or a box thereof, dropStartValue = new BigDecimal(newCounterValue); should do what you want.

Categories