List Contains() comparing Doubles in Java / Groovy - java

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.

Related

Sum of BigDecimal(s) created from possible null Double

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

Recursive Descent Parser - Adding Unitialized Variables

So, I have a recursive descent parser that analyzes a mathematical expression in infix. The expression is tokenized, parsed with the aforementioned parser, which generates an AST on the fly (with nodes for each type of expression) and evaluates the final value. I am handling all of these values as doubles; so, I use this parser like so:
Parser parser = new Parser();
try {
ExpressionNode expression = parser.parse("5 + 4*cos(pi)");
System.out.println("The value of the expression is "
+ expression.getValue());
} catch (ParserException | EvaluationException e) {
System.out.println(e.getMessage());
}
}
With Exceptions I defined myself.
The line expression.getValue() returns a double, and the way my parser works is that every expression node returns a double, so each branch is evaluated bottom up, until it finally ends up at one double answer.
The thing is, I want to handle unitialized variables in my expressions, like so if I wanted to parse 5 + x (where x is not initialized prior) the expression's value would return 5 + x.
Would I have to change my expression node's getValue() return type to a String? I feel like that would complicate and bloat the program, and there must be a better way to accomplish this. Does anyone have any experience with this type of thing?
I know the description of my parser might have been a little vague, so this is where I learned how to implement most of it.
I assume in your expression tree you have classes defined for operators and constants. You will need to define a new class for variables.
You will then need to add a method like getAllVariables which can return all variables below any point in the tree.
The I suggest you change getValue to accept a Map<String, Double> to provide values for any variables at evaluation time. This will need to be ignored by all nodes other than variables which will return their own value from the map. If they don't find a mapping for themselves as a key they should throw an EvaluationException.
Finally if you want to be able to print out the expression as a string then that's really a separate method to your getValue. Perhaps getExpressionText. Then each class can override this to return a String representing the expression from that point down with the variables just returning the variable name.
So now once you've parsed your expression you can get all variables, prompt the user for values for them, evaluate the expression for given values (catching the exception if any are undefined) and print it out again.
ExpressionNode expression = Parser.parse("x + 5 * y");
System.out.println(expression.getExpressionText());
System.out.println(expression.getAllVariables());
Map<String, Double> variableValues = new TreeMap<>();
variableValues.put("x", 4);
variableValues.put("y", -2);
System.out.println("Evaluates to " + expression.getValue(variableValues));
I would expect your Variable class to end up looking something like:
public class Variable implements ExpressionNode {
private final String name;
public double getValue(Map<String, Double> variableValues) {
if (variableValues.containsKey(name)) {
return variableValues.get(name);
} else {
throw new EvaluationException(name + " is undefined");
}
}
public String getExpressionText() {
return name;
}
public List<String> getAllVariables() {
return Arrays.asList(name);
}
}
Another common operation you might want to perform on an expression tree is to simplify it. That essentially means to evaluate to a constant anything that can be evaluated. In my view the best way to do this is to return a new simplified tree rather than changing the current tree. So I recommend adding a new method to ExpressionNode:
public ExpressionNode simplify();
For variables and constants this would just return this. For operators it needs to do something more complicated. Something like:
class Operator implements ExpressionNode {
public ExpressionNode simplify() {
if (getAllVariables().isEmpty()) {
return new Constant(getValue());
} else {
Operator simplified = new Operator(operation);
for (ExpressionNode operand: operands) {
simplified.addOperand(operand.simplify());
}
return simplified;
}
}
Hopefully you see what that does. If the operation can be completely evaluated then it's converted to a constant. Otherwise it remains an operation but each of its operands is simplified in turn.
So now if you want to simplify an expression you can do:
System.out.println(Parser.parse("7 * 2 + x * 3").simplify().getExpressionText());
Which will return "14 + x * 3".
If you then want to get even more sophisticated you can build awareness of association and distribution into your operators and change simplify so that it reorganises the tree to group variables. But I believe that's a bit beyond the scope of this question!

Find type of object from value of String

I need a way to return the type of an object (as a string, or class of the object, whichever is easier) given a string with the value in it.
I could parse it with each of the types I want, but there are problems associated with that (such as an int may also be parsed as a long, a float can be parsed as a double). Here's my sketch:
private String typeOf(String test) {
if (test == "true" || test == "false")
return "boolean";
else if (// its a number)
// figure out a way to parse all number types?
// return corresponding type
else
// can't be parsed with any boolean or number types... just a string
return "string";
}
The types I am checking are: String, long, int, short, byte, byte[], float, and double.
Remember I need the SPECIFIC type in order to accomplish the make-or-break functionality of this program. Any help is appreciated.
I'm trying to make a Named Binary Tag (specifications here) that holds a specific type of data given by user input (a JOptionPane - input dialog). In order to make the correct type of tag, I need to know the type of the data given. (Is there a way to get the input from the user where I can avoid the String problem entirely?) Having a String to work with in the first place has become the main source of my issue.
To start your String checking is incorrect. Aside from that think about the different datatypes and their possible values.
An int or Integer's possibles values all lie within the ranges of a long. The same is true for Floats and Doubles. You will need to figure out which Datatype's ranges are subsets of which and test in that order. As an example here is a quick snippit for testing for Integers and Longs.
private String typeOf(String suppliedTest) {
String test = suppliedTest.strip().toLower();
if (test.equals("true") || test.equals("false"))
return "boolean";
try {
int testInt = Integer.parseInt(test);
return "integer";
} catch (NumberFormatException e) {}
try {
long testLong = Long.parseLong(test);
return "long";
catch (NumberFormatException e) {}
...
}
You can use class specific parsing methods to check, if a String represents a certain type, such as
Double.parseDouble()
Integer.parseInt()
these methods will throw NumberFormatException if the input string does not contain a value, that represents the appropriate type.
You don't have enough different to know the difference. All you can do is find the smallest type when can represent that data. a 0 could be a String, long, int, short, byte, float or double. You will need to decide which would be the most appropriate response.

Integer Enum and Unboxing

public class Document{
private Integer status;
// get()/set()
}
Then an enum:
public enum DocumentStatusEnum {
ACTIVE_DOCUMENT(2060),CANCELLED_DOCUMENT(2061),DRAFT_DOCUMENT(2062),PROCESSED_DOCUMENT(2063);
private final Integer value;
private DocumentStatusEnum(Integer value){
this.value = value;
}
public Integer getValue(){
return value;
}
}
In a method I'm using the above method as below:
Document d = new Document();
d.setStatus(2063);
if (d.getStatus() == DocumentStatusEnum.PROCESSED_DOCUMENT.getValue()){
{
// print true;
}
else{
// print false;
}
I get true here. Looks alright. In the same method, After couple of lines, I do this:
d.setStatus(2060)
if (d.getStatus() == DocumentStatusEnum.ACTIVE_DOCUMENT.getValue()){
// print true
}
else{
// print false
}
I get a false. I researched and found something about caching and boxing features in Java. I converted the enum definition as this:
public enum DocumentStatusEnum {
ACTIVE_DOCUMENT(2060),CANCELLED_DOCUMENT(2061),DRAFT_DOCUMENT(2062),PROCESSED_DOCUMENT(2063);
private final int value;
private DocumentStatusEnum(int value){
this.value = value;
}
public int getValue(){
return value;
}
}
Now, no issues. I get true in both cases.
Question is why this happening? I feel this behaviour is extremely unstable. It's a large application I'm dealing with and I'm using Integer == Integer comparison every where. Am I safe here?
Integer extends Object and therefore == is defined as reference equality, not value equality.
When comparing Integer with int, the Integer will be unboxed to an int, and the two operands will be compared for value equality. (Unless the Integer value is null, in which case NullPointerException will be thrown instead.) But Integer == Integer is never safe.
That said, because by default the runtime pre-allocates Integer instances for small integers (-128 through 127, according to the OpenJDK source), you can often get Integer == Integer to work for small values. But that behavior does not hold for larger values, and it is never required to hold. So you should never assume that two instances of Integer (or String, or any Object) will compare equal using ==, unless you are explicitly looking for reference equality.
You should use int instead of Integer, unless you need to handle null values.
There are indeed issues with comparing Integer objects. For example, the following will evaluate to false:
boolean test = (new Integer(1) == new Integer(1));
System.out.println(test); // "false"
These are just objects like any other. The == operator, when used with objects, only evaluates to true if they are the exact same Java object (as opposed to the equals() method, which can be overridden to compare the internals).

How to compare Integer correctly in Java [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Integer wrapper class and == operator - where is behavior specified?
I known Java integer use cache in -127~128.
If
Integer i = 1;
Integer j = 1;
Integer m = 128;
Integer n = 128;
i == j // true
m == n // false
But I met a strange phenomenon.First,look at following snippet.
List<CustomerNotice> customerNotice = findByExample(example); // use Hibernate findByExample method
for(CustomerNotice n : customerNotice){
if(n.getConfirmStatus() == NoticeConfirmStatus.UNCONFIRMED.getValue()){
// do sth
}
}
public enum NoticeConfirmStatus{
UNCONFIRMED(1), //
CONFIRMED(2), //
FAILED_TO_CONFIRM(3); //
private final Integer value;
private NoticeConfirmStatus(Integer value) {
this.value = value;
}
public Integer getValue() {
return this.value;
}
}
public class CustomerNotice {
#Column(name = "CONFIRM_STATUS")
private Integer confirmStatus;
public Integer getConfirmStatus() {
return this.confirmStatus;
}
public void setConfirmStatus(Integer confirmStatus) {
this.confirmStatus = confirmStatus;
}
}
Although the if expression is not recommended, I think it will be return true,because n.getConfirmStatus()==1, but the result is false.I'm very confusing.
In addition, theList<CustomerNotice> customerNotice acquired by Hibernate findByExample method. Is there some Autoboxing or new operation when retrieve the resultset?
Thank you.
SHORT: (answers question)
If you want to compare Integers as the objects, you should use .equals:
i.equals(j);
m.equals(n);
With this, they should both return true. But if you really want to use ==, you need to get the primitive int value:
i.intValue() == j.intValue();
m.intValue() == j.intValue();
LONG: (explains answer)
The basis of this is that Objects are always stored separately in memory (except for some special cases like m=n), and to be compared properly, they need to be broken down into primitive types that can be compared successfully using ==.
Every Object has a .equals() method, which is inherited from Object as its superclass. However, it must be overridden to do a proper comparison. Integer overrides this method to compare to Integer objects successfully, while using == checks to see if both objects point to the same space in memory, and because two instances of an Object cannot point to the same space in memory, this will always return false.
However, as your code points out, there are some special cases that work, like these:
Your code uses a Integer i = 1, which is considered a "standard instance" and is able to be compared using ==.
If you set one Object equal to another using =, Java tells both objects to point to the same location in memory, which means that == will return true.
There are many others, but those are the two that come to mind and seem relevant.
You'll drive yourself crazy and waste a lot of time trying to figure out specific cases where this works or does not work. It depends on the implementation of code which isn't always visible to you.
The bottom line: never, ever, use == to compare Integer instances, period. As you have seen, it works sometimes, under some circumstances, and fails miserably the rest of the time. If you have a method that returns an Integer, then assign the value to an int, and then you can use == to compare that int to another int.

Categories