-1

I have two LongProperty (there are no decimal places in a long) variables (longProperty1 and longProperty2). I need to divide them and I need to keep the division result in a DoubleProperty (there are decimal places in a double) variable (result) without losing decimal places.

final DoubleProperty result = new SimpleDoubleProperty(0.0);
final LongProperty longProperty1 = new SimpleLongProperty(45);
final LongProperty longProperty2 = new SimpleLongProperty(7);
result.bind(longProperty1.divide(longProperty2));
System.out.println(result.get()); //print: "6.0" instead of "6.428571428571429" (lost decimal places)

longProperty1 and longProperty2 are of type LongProperty because they receive very large numbers, so I can't cast them to DoubleProperties.

On the other hand, the result will receive a value from 0.0 to 1.0 (for example: 0.0, 0.2975, 0.5378, 0.9853, 1.0), because in my real problem longProperty1 <= longProperty2(for example: 500/600=0.8333, 1/2=0.5, 1897/5975=0.3174, ...).

How to do this?

user1803551
  • 12,965
  • 5
  • 47
  • 74
Douglas
  • 101
  • 4

2 Answers2

1

The methods provided LongProperty (and by other NumberExpressions) such as divide are convenience methods. You can create a custom binding that does whatever you want:

final DoubleProperty result = new SimpleDoubleProperty(0.0);
final LongProperty longProperty1 = new SimpleLongProperty(812323534);
final LongProperty longProperty2 = new SimpleLongProperty(956745323);
result.bind(Bindings.createDoubleBinding(() -> longProperty1.longValue() / (double) longProperty2.longValue(),
    longProperty1, longProperty2));
System.out.println(result.get());
longProperty1.set(612323534);
System.out.println(result.get());

Bindings is a utility class for creating bindings. Here I created a custom binding that returns a double by casting the division of longs to double. You will lose precision here.

The output of the above is:

0.8490488685670847
0.6400068223798362
user1803551
  • 12,965
  • 5
  • 47
  • 74
0

You should use BigDecimal for your calculations.
LongProperty is just a wrapper for usual long value, so no decimal points.

You can try doing longProperty1.divide(longProperty2.doubleValue()) as well, which would call DoubleBinding divide(final double other), but I think this would remove the point of using LongProperty.

Aleksandr
  • 428
  • 2
  • 8
  • 14
  • `doubleValue()` doc says: [`"Returns the value of this ObservableNumberValue as a double. If the value is not a double, a standard cast is performed."`](http://docs.oracle.com/javase/8/javafx/api/javafx/beans/binding/LongExpression.html#doubleValue--); Can the **cast** cause me to lose the original long value stored in my LongProperty? – Douglas Sep 17 '17 at 17:06
  • @Douglas, `double` can hold extremely large numbers, but you would lose precision quite fast, so it's definitely not recommended for precise calculations. So yes, it will probably cause you to lose the original long value. – Aleksandr Sep 17 '17 at 17:14
  • @Douglas what do you actually mean by big numbers? If it's less than 10_000 or 100_000, I don't think that you would have any problems with `double`. But you shouldn't use it for important calculations like currency. – Aleksandr Sep 17 '17 at 17:24
  • Okay, I do not need high precision in `result`, but I need `result` to be updated whenever the value of `longProperty1` or `longProperty2` is changed; using `longProperty2.doubleValue()` I bind with a constant value, so that `result` will not be updated when `longProperty2` is changed. – Douglas Sep 17 '17 at 17:30