#how would i change this to not have bigdecimals

1 messages · Page 1 of 1 (latest)

viscid chasm
#
// this finds the average of all the floats in attack/speedValues,
// then does average += average * 0.8 or 0.5, and rounds it up to the
// tenths place. the resulting value is the attackDamage/speedBaseline.
var attack = new BigDecimal("0");
    for (final var f : attackValues) {
    attack = attack.add(new BigDecimal(Float.toString(f)));
}
attack = attack.divide(new BigDecimal(Integer.toString(attackValues.size())), 3, CEILING);
attackDamageBaseline = attack.add(attack.multiply(BigDecimal.valueOf(.08)))
        .setScale(1, CEILING).floatValue();
```i want to make this to not have bigdecimals so it has better performance, but idk how i would do that (i want the same result +-0.1)
violet bronzeBOT
#

<@&987246399047479336> please have a look, thanks.

violet bronzeBOT
#

While you are waiting for getting help, here are some tips to improve your experience:

Code is much easier to read if posted with syntax highlighting and proper formatting.

If nobody is calling back, that usually means that your question was not well asked and hence nobody feels confident enough answering. Try to use your time to elaborate, provide details, context, more code, examples and maybe some screenshots. With enough info, someone knows the answer for sure.

Don't forget to close your thread using the command </help-thread close:1027500463647621170> when your question has been answered, thanks.

ocean parrot
#

You could try just using normal primitives, and see if it produces a good result

#

new BigDecimal(Float.toString(f))
This is not a good way to do this, the documentation for that BigDecimal constructor says:

Translates the string representation of a BigDecimal into a BigDecimal.
You can just cast f to a double

#

Same applies to this Integer.toString(attackValues.size())
This can be replaced with just attackValues.size()

#

The second parameter in setScale is the roundingMode, why do you put in a variable called CEILING?

setScale(int newScale, int roundingMode)

#

That is the end of my code rant ^-^

viscid chasm
#

thats deprecated

#

CEILING is a static import of java.math.RoundingMode.CEILING

ocean parrot
#

Ah that makes sense

zenith vault
#

Even using BigDecimal you can remove several allocations.

  1. BigDecimal.ZERO instead of a new BigDecimal
  2. rearranging a + a * 0.08 to a * 1.08
  3. statically creating the 1.08 BigDecimal value.
  4. Multiplying before dividing (a) eliminating a scaling operation and (b) making the division a scale-1 operation (able to bail out earlier)

Leading to something like...

var attack = BigDecimal.ZERO;
for (final var f : attackValues) {
    attack = attack.add(BigDecimal.valueOf(f));
}

return attack
    .multiply(BD_1_08)
    .divide(BigDecimal.valueOf(attackValues.size()), 1, RoundingMode.CEILING)
    .floatValue();
viscid chasm
#

doesnt ZERO have a scale of 0

zenith vault
#

Removing BigDecimal entirely is mostly complicated by the ceiling operation.

The first part is trivial though

var attackTotal = 0.0;
for (final var f : attackValues) {
    attackTotal += f;
}

var unscaled = attackTotal * 1.08 / attackValues.size();

Because Java doesn't offer a precision-specifying ceiling operation, the easiest is probably to scale up, adjust for precision, truncate to int, and scale down.

var scaledUp = (int) (unscaled * 10 + 0.9999999);
return (scaledUp / 10.0f);

Another big gain would be to look at using float[] instead of List<Float> and eliminate all of the boxing and poor locality of reference overhead (not to mention all of the pointer storage).

viscid chasm
#

would doing (float)(Math.ceil(unscaled * 10) / 10) work?

#

also, i dont think just adding 0.9999999 would work, because unscaled might be negative

zenith vault
#

Yeah Math.ceil might be the better option.

viscid chasm
#

so my code looks like this now:```java
for (final var f : attackValues) {
attackDamageBaseline += f;
}
attackDamageBaseline /= attackValues.size();
attackDamageBaseline *= 1.08;
attackDamageBaseline = (float)(Math.ceil(attackDamageBaseline * 10) / 10);

#

which i simplified to:java for (final var f : attackValues) { attackDamageBaseline += f; } attackDamageBaseline = (float)(Math.ceil(attackDamageBaseline / attackValues.size() * 10.8) / 10);

zenith vault
#

With floating point, multiply then divide, to minimise arithmetic error. In your case you probably encounter a difference - but it's a good habit.