Check the decimal places of a real number

I am looking for a way to check the number of decimal places of a real number and respond accordingly.

In particular, I would like to check the number of decimal places of a real number typed by the player and ask them to enter the number again if the number has more than 2 decimal places.

See WWI 15.5 Arithmetic and WWI 15.6 Powers and logarithms.

To decide whether (N - real number) has at most (M - number) decimal places:
	let D be 1.0 divided by (10 to the power (1.0 times M));
	if "[N]" is "[N to the nearest D]":
		decide yes;
	otherwise:
		decide no.

When play begins (this is the demonstrate decimal place test rule):
	showme whether or not 1.239 has at most 1 decimal places;
	showme whether or not 1.239 has at most 2 decimal places;
	showme whether or not 1.239 has at most 3 decimal places;
	showme whether or not 1.239 has at most 4 decimal places;
	showme whether or not 1.239 has at most 5 decimal places.

NOTE: Interestingly, under 6M62 the original version of the above does not work correctly if the number of decimal places checked is the same that the number tested actually has in several cases. It appears that even though the real number values used in the comparison display the same they can be different as raw values (e.g. off by 1 if considered as an integer). The phrase has been updated to convert to strings as a quick fix.

1 Like

A good solution! But if you’re going to be comparing them as strings anyway, the math seems like overkill.

To decide what number is the number of decimal places in (N - real number):
    if "[N]" matches the regular expression "\d*\.(\d+)":
        decide on the number of characters in text matching subexpression 1;
    decide on zero.
1 Like

Watch out for numbers like 12.38999999999, though.

It’s generally not safe to assume that real values are exact. I mean in any language, not just Inform.

3 Likes

Cool, thanks a lot!

Now I’m extra interested. I understood that precision was a limit, but I had thought that it applied only when storing the number, such that while many mathematical reals in the set X might map to a single stored real value, it was not the case that many stored real values could map to the same mathematical real. (I think I thought that because I noticed that REAL_NUMBER_TY_Compare() just looks at raw values.)

Is that not the case? Or is it theoretically the case but it doesn’t matter because there is further blurring going on during the operations of the “extraction” (i.e. conversion to an output string)?

I just mean that, well, where is that 1.239 coming from? Did you parse the string “1.239” from player input? Did you divide 1239 by 1000? Did you multiply 2.478 by 0.5? It’s not safe to assume that all of these operations will produce the same raw value, or that they will all render to “1.239” when converted to a string.

There’s another, more serious, point to be wary on rounding/truncating numbers: that a small number, say, .0003 became truncated to zero then used as a divisor, leading to crash/halt of the story file…

Best regards from Italy,
dott. Piergiorgio.

A further possible issue is that computers do not store real numbers with guaranteed accuracy. They convert numbers to base 2, and with integers that is fine, with real numbers you can strange rounding issues. I would suggest storing the number as 100 times the value, so you can store it as a whole number, and divide that by 100 whenever the player sees it.

[This is based on wat computers do; I am only guessing it is true of Inform but it would be very surprising ig it was not.]

This is the issue we have been discussing.

Inform uses 32-bit floating-point, which is less exact than what most programming languages use but same idea. At some point it will switch to 64-bit floating point which is what pretty much everybody else uses.

Okay, then take my post as explaining what the issue is, because I really did not get that impression.

And I would still recommend using an integer to store the number.