Skript icon indicating copy to clipboard operation
Skript copied to clipboard

ExprDecimalPlaces

Open Absolutionism opened this issue 6 months ago • 4 comments

Problem

There is no expression allowing users to get how many decimal places a number goes into. Also was requested in the linked issue.

Solution

Adds ExprDecimalPlaces allowing users to quickly and easily get how many decimal places a number goes into.

Testing Completed

ExprDecimalPlaces.sk

Supporting Information

N/A


Completes: #7948 Related: none

Absolutionism avatar Jun 15 '25 22:06 Absolutionism

I'm not sure this should be based off of the doublevalue.toString at all.

What do you suggest? I was originally going to make it:

"[the] number of decimal places of %numbers% [limited:with a (limit|cap) of %-integer%]
"[the] number of decimal places of %numbers% [unlimited:with no (limit|cap)]

So default behavior would use the number accuracy option in the config limited would limit to the provided integer unlimited no limit

Absolutionism avatar Jun 17 '25 11:06 Absolutionism

I'm not sure this should be based off of the doublevalue.toString at all.

What do you suggest? I was originally going to make it:

"[the] number of decimal places of %numbers% [limited:with a (limit|cap) of %-integer%]
"[the] number of decimal places of %numbers% [unlimited:with no (limit|cap)]

So default behavior would use the number accuracy option in the config limited would limit to the provided integer unlimited no limit

Well I think you should be using Skript.toString() to convert the number to a string, which will respect the number accuracy. Alternatively, you can forgo a toString entirely and instead repeatedly divide by 10 until x % 1 is within epsilon of 0/1. You should try both and see how well each works

sovdeeth avatar Jun 17 '25 18:06 sovdeeth

Alternatively, you can forgo a toString entirely and instead repeatedly divide by 10 until x % 1 is within epsilon of 0/1.

So something like this?

for (Number number : numbers.getArray(event)) {
	if (!(number instanceof Double doubleValue))
		continue;
	long decimalPlace = 0L;
	double x = Double.valueOf(doubleValue);
	while (Math.abs(x % 1) > 1e-9) {
		x /= 10;
		decimalPlace++;
	}
	decimalPlaces.add(decimalPlace);
}

Absolutionism avatar Jun 18 '25 00:06 Absolutionism

Alternatively, you can forgo a toString entirely and instead repeatedly divide by 10 until x % 1 is within epsilon of 0/1.

So something like this?

for (Number number : numbers.getArray(event)) {
	if (!(number instanceof Double doubleValue))
		continue;
	long decimalPlace = 0L;
	double x = Double.valueOf(doubleValue);
	while (Math.abs(x % 1) > 1e-9) {
		x /= 10;
		decimalPlace++;
	}
	decimalPlaces.add(decimalPlace);
}

yes but i should have said multiply not divide and make sure you check for the mod result being like 0.99999999

sovdeeth avatar Jun 18 '25 03:06 sovdeeth