In order to avoid possible loss of precision in Java operation on Double objects i.e.:
Double totalDouble = new Double(1590.0);
Double taxesDouble = new Double(141.11);
Double totalwithTaxes = Double.sum(totalDouble,taxesDouble);
//KO: 1731.1100000000001
System.out.println(totalwithTaxes); // 1731.1100000000001
I wrote this code, where totalDouble and taxesDouble could be also null:
Double totalDouble = myObject.getTotalDouble();
Double taxesDouble = myObject.getTaxesDouble();
BigDecimal totalBigDecimalNotNull = (totalDouble==null) ? BigDecimal.valueOf(0d):BigDecimal.valueOf(totalDouble);
BigDecimal taxesBigDecimalNotNull = (taxesDouble==null) ? BigDecimal.valueOf(0d):BigDecimal.valueOf(taxesDouble);
BigDecimal totalWithTaxesBigDecimal = totalBigDecimalNotNull.add(taxesBigDecimalNotNull);
System.out.println(totalWithTaxesBigDecimal);
Is there a better way (also with third part libraries i.e. guava, etc) to initialize BigDecimal in this cases (zero if Double is null and Double value otherwise)?
Not really. That is to say, you're still going to need to make a decision based on whether or not the value is null, but you can do it cleaner if you use the Optional pattern.
You can change your getTotalDouble and getTaxesDouble returns to Optional<Double> instead to mititgate having to do the ternary...
public Optional<Double> getTotalDouble() {
return Optional.ofNullable(totalDouble);
}
public Optional<Double> getTaxesDouble() {
return Optional.ofNullable(taxesDouble);
}
...then, you can use the conditional evaluation provided by Optional itself to evaluate and return a default value.
BigDecimal totalBigDecimalNotNull =
BigDecimal.valueOf(myObject.getTotalDouble().orElse(0d));
A simplification would be to return Optional<BigDecimal> instead, as opposed to transforming the value that you want in this fashion.
As an addendum, be careful when talking about precision. There is standing advice to use either int or long instead to ensure you don't lose any coin precision.
Whether you use Optional or not I recommend creating a static helper method so that you don't have to repeat yourself. e.g.:
public static BigDecimal bigDecimalValueOfOrZero(Double val) {
return val == null ? BigDecimal.ZERO : BigDecimal.valueOf(val);
}
Related
So I have this expression:
[8.42431001E10].contains(getSomeValue('000000084243100100'))
the getSomeValue(String value) converts the string to a double.
public Object getSomeValue(String value) {
if (NumberUtils.isNumber(value)) {
try {
result = NumberUtils.createDouble(value);
} catch (Exception e) {
result = value;
}
} else {
result = value;
}
return result;
}
Which means that getSomeValue('000000084243100100') returns 8.42431001E10
However the expression above [8.42431001E10].contains(getSomeValue('000000084243100100')) returns false even though i expect it to be true.
when converting everything to string such as this one:
["8.42431001E10"].contains(getSomeValue('000000084243100100').toString()) returns true.
I want to understand how to make it return to true as a double value, not string.
I have also tried doing this:
[8.42431001E10].contains(Double.valueOf(getSomeValue('000000084243100100')))
But still false.
Please help. Thank you!
The "number literal" in Groovy gives you a BigDecimal (instead of
float/double like in many other (jvm-)languages). And BigDecimal is
accurate and double/float is not (it's an approximation for the sake of
speed over accuracy).
def x = 8.42431001E1
println x.getClass()
// → class java.math.BigDecimal
println(x==Double.valueOf('000000084243100100'))
// → false
So you have to cast one side to the same type to make them comparable.
Since both numbers actually don't have fractions this begs the question,
why not to use BigInteger in the first place for both sides anyway.
I would like to know when I am checking for integers input, should I use int or Integer for checking?
Below is some mock-up codes:
This one uses int:
public State editState (int stateID, String stateCode) {
if (stateID == 0) {
throw new Exception("State id not set.");
}
...
State s = new State();
...
return s;
}
This one uses Integer:
public State editState (Integer stateID, String stateCode) {
if (stateID == null) {
throw new Exception("State id not set.");
}
...
State s = new State();
...
return s;
}
Which approach is better in use?
when you will invoke editState(..,..) and stateId is not set then two cases arise-
1)editState(0,"some code");
2)editState(null,"some code");
It depends upon the criteria you set for the unacceptance of stateID.
If you set criteria for unacceptance as null then you will have to use 'Integer'
and if 0 then you can use both 'Integer' and 'int' ...
so it depends upon the criteria you set at the invoking side..
And i think Integer (wrapper class ) is better due to excellent auto boxing ,unboxing features
as well as various methods provided to you for manipulations if required...
There is no much difference performance wise or functionality wise. Both would be almost equal. It depends more on how the input is in the method invoking the editState(...) method. If the invoking method has primitive type int or wrapper Integer, corresponding editState(...) is better to use.
Also, if the invoking method has the possibility of different numeric types (byte, short etc.) that fits into int, then first one is preferred. Similarly if it has object that can be autoboxed to Integer, then second one is preferred.
Well, in Java an int is a primitive while an Integer is an Object. Meaning, if you made a new Integer:
Integer i = new Integer(6);
You could call some method on i:
String s = i.toString(); //sets s the string representation of i
Whereas with an int:
int i = 6;
You cannot call any methods on it, because it is simply a primitive. So:
String s = i.toString(); //will not work!!!
would produce an error, because int is not an object.
I think if you have not any requirement to use such operation then go with int instead of Integer and you can also avoid a unnecessary Java object creation.
For later reference:
Operations o = new Operations(); //class containing the operation methods
HashMap<String, Method> ops = new HashMap<String, Method>();
I'm working on a program that will parse a mathematical expression input via console or eventually maybe a GUI.
Currently, I have a class called "Operations" which has various basic math functions (more will be added later, just testing right now). In another class, I have a method which calculates the result by taking an operand, the successive operator, and another operand, and invoking a method to evaluate the expression. It stores the info necessary to the calculation in:
double numOne = //...
char operator = //...
double numTwo = //...
double result = //...
Now I don't want to have a long switch/case statement or if statement saying:
if (operator.equals("+")) //I know .equals() doesn't use chars; it's an example
o.add(numOne, numTwo);
else if (operator.equals("-"))
o.subtract(numOne, numTwo);
on and on for every operation. That's why I tried creating a HashMap<String, Method> to store the operator (String) and the method which should be called. Basically, in the current class' constructor, I put:
ops.put("+", o.getClass().getMethod("add", double.class, double.class));
ops.put("-", o.getClass().getMethod("subtract", double.class, double.class));
//etc. Which in and of itself is also pretty lengthy
Now to once the method is identified via operator, I need another method to return a Method to call.
private Method getMethodFromKey(HashMap<String, Method> map, char op) {
Method method = null;
for (Map.Entry<String, Method> e: map.entrySet()) {
if (e.getKey().equals(op))
method = e.getValue();
}
return method;
}
Finally, once I have the correct method, I can call it with:
getMethodFromKey(ops, operator).invoke(o, numOne, numTwo);
That all works great. My problem is, the method(s) I am/will be invoking are getter methods; they return a double. Example:
public double add(double one, double two) {
double answer = 0;
answer = one + two;
return answer;
}
I guess this is all just a long-winded way of asking is there a way to assign the returned value of an innvoked method? Something like:
result = getMethodFromKey(ops, operator).invoke(o, numOne, numTwo); //This doesn't work :(
Any help is appreciated. Additionally, if my aproach is completely wrong, I would appreciate a bump in the right direction.
DISCLAIMER: I'm relatively inexperienced at Java and known for overcomplicating things, so please point out any grievous flaws in my design. :)
invoke() returns Object and since Java does not know how to assign an Object to a double this won't compile. invoke starts by boxing the double from the method into a Double. You have to cast it now from Object to Double (and could then call .doubleValue() but that's done automatically) for that to work.
I'm [...] known for overcomplicating things, so please point out any grievous flaws in my design. :)
Using reflection instead of an interface. A Method is a function object. But it's not type-safe to use. An interface can do the same without those problems.
interface Operation {
double evaluate(double a, double b);
}
Then put objects that implement the interface in your map:
ops.put("+", new Operation() {
public double evaluate(double a, double b) {
return a+b;
});
and you can do
double result = getMethodFromKey(ops, operator).evaluate(numOne, numTwo);
The need to cast is gone.
If you're sure that all of your operations are going to be on a single class (no extensibility), then you should consider using an enum instead. You can add an instance field to the enum to represent the character command corresponding to the operation and then have an abstract evaluate method that's implemented by each enum value.
If invoke() is returning an Object that you know is a double, you can cast it like so:
result = (Double) getMethodFromKey(ops, operator).invoke(o, numOne, numTwo);
Since double is a primitive, which is not of type Object, you need to cast it to a Double, and through unboxing, we get a double.
I wish to create a HashSet for real numbers (at present Doubles) using a defined tolerance (epsilon), (cf Assert.assertEquals(double, double, double)
Since using Double.equals() only works for exact equality and Double is a final class I can't use it. My initial idea is to extend HashSet (e.g. to DoubleHashSet), with a setEpsilon(double) method and create a new class ComparableDouble where equals() uses this value from DoubleHashSet. However I'd like to check whether there are existing solutions already and existing F/OSS libraries.
(In the future I shall want to extend this to tuples of real numbers - e.g. rectangles and cubes - so a generic approach is preferable
NOTE: #NPE has suggested it's impossible. Unfortunately I suspect this is formally correct :-) So I'm wondering if there are approximate methods ... Others must have had this problem and solved it approximately. (I already regularly use a tool Real.isEqual(a, b, epsilon) and it's very useful.) I am prepared to accept some infrequent errors of transitivity.
NOTE: I shall use a TreeSet as that solves the problem of "nearly equals()". Later I shall be comparing complexNumbers, rectangles (and more complex objects) and it's really useful to be able to set a limit within which 2 things are equal. There is no simple natural ordering of complexNumbers (perhaps a Cantor approach would work), but we can tell whether they are nearly equal.
There are some fundamental flaws in this approach.
HashSet uses equals() to check two elements for equality. The contract on equals() has the following among its requirements:
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
Now consider the following example:
x = 0.0
y = 0.9 * epsilon
z = 1.8 * epsilon
It is clear that your proposed comparison scheme would break the transitivity requirement (x equals y and y equals z, yet x doesn't equal z). In these circumstances, HashSet cannot function correctly.
Furthermore, hashCode() will produce additional challenges, due to the following requirement:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
The hashCode() requirement can be sidestepped by using a TreeSet instead of HashSet.
What I would do is round the doubles before using them (assuming this is appropriate)
e.g.
public static double roundByFactor(double d, long factor) {
return (double) Math.round(d * factor) / factor;
}
TDoubleHashSet set = new TDoubleHashSet(); // more efficient than HashSet<Double>
set.add(roundByFactor(1.001, 100));
set.add(roundByFactor(1.005, 100));
set.add(roundByFactor(1.01, 100));
// set has two elements.
You can wrap this behaviour in your own DoubleHashSet. If you want to reserve the original value you can use HashMap or TDoubleDoubleHashMap where the key is the rounded value and the value is the original.
I have implemented #NPE's approach (I have accepted his/her answer so s/he gets the points :-) and give the code here
//Create a comparator:
public class RealComparator implements Comparator<Double> {
private double epsilon = 0.0d;
public RealComparator(double eps) {
this.setEpsilon(eps);
}
/**
* if Math.abs(d0-d1) <= epsilon
* return -1 if either arg is null
*/
public int compare(Double d0, Double d1) {
if (d0 == null || d1 == null) {
return -1;
}
double delta = Math.abs(d0 - d1);
if (delta <= epsilon) {
return 0;
}
return (d0 < d1) ? -1 : 1;
}
/** set the tolerance
* negative values are converted to positive
* #param epsilon
*/
public void setEpsilon(double epsilon) {
this.epsilon = Math.abs(epsilon);
}
and test it
public final static Double ONE = 1.0;
public final static Double THREE = 3.0;
#Test
public void testTreeSet(){
RealComparator comparator = new RealComparator(0.0);
Set<Double> set = new TreeSet<Double>(comparator);
set.add(ONE);
set.add(ONE);
set.add(THREE);
Assert.assertEquals(2, set.size());
}
#Test
public void testTreeSet1(){
RealComparator comparator = new RealComparator(0.0);
Set<Double> set = new TreeSet<Double>(comparator);
set.add(ONE);
set.add(ONE-0.001);
set.add(THREE);
Assert.assertEquals(3, set.size());
}
#Test
public void testTreeSet2(){
RealComparator comparator = new RealComparator(0.01);
Set<Double> set = new TreeSet<Double>(comparator);
set.add(ONE);
set.add(ONE - 0.001);
set.add(THREE);
Assert.assertEquals(2, set.size());
}
#Test
public void testTreeSet3(){
RealComparator comparator = new RealComparator(0.01);
Set<Double> set = new TreeSet<Double>(comparator);
set.add(ONE - 0.001);
set.add(ONE);
set.add(THREE);
Assert.assertEquals(2, set.size());
}
I am looking for a robust Map in Java, where the key lookup would take into account that Double has a limited precision (something around 1e-15 or 1e-16). Where could I find such a thing?
EDIT: Following Jon's advice I think it would make sense to define equivalence. One idea would be to center these at numbers rounded to 15 most relevant decimal digits. Other numbers would be rounded (in any consistent way - the fastest to implement). Would this make sense? What would be the best implementation?
I'd suggest you to use TreeMap and implement your own custom comparator that compares 2 double values taking into account the required precision.
IMHO The best approach is to normalise the values before adding or looking up values. e.g. by using rounding.
BTW: You can use TDoubleObjectHashMap which support custom hash strategies and uses primitive double keys.
I'm not completely sure what you need it for, but you can implement a wrapper around Double and override its hashCode() and equals() methods to meet your "limited precision" lookup. Therefore any Map implementation will be robust, because it relies on hashCode() an equals() for key lookup.
Of course, your map will be in a form Map<DoubleWrapper, smth>.
Summing up answers and comments above, I ended up with the following wrapper (which probably doesn't handle NaN atm):
public static class DoubleWrapper {
private static final int PRECISION = 15;
private final Double roundedValue;
public DoubleWrapper(double value) {
final double d = Math.ceil(Math.log10(value < 0 ? -value: value));
final int power = PRECISION - (int) d;
final double magnitude = Math.pow(10, power);
final long shifted = Math.round(value*magnitude);
roundedValue = shifted/magnitude;
}
public double getDouble() {
return roundedValue;
}
#Override
public boolean equals(Object obj) {
return roundedValue.equals(obj);
}
#Override
public int hashCode() {
return roundedValue.hashCode();
}
}