Mathematical computation in I7

Today I found out the hard way that I7 doesn’t have any sort of reasonable order of operations or operator precedence on arithmetic computations, so that an expression like “100 * x + y” for x = 2, y = 1 returns 300 rather than 201. (Apparently the developers consider this a feature rather than a bug.) Is there some sort of function or wrapper analogous to a Linux-style expr for parsing mathematical commands? I do actually have a bit of arithmetic to do in a game I’m writing, and it can’t be that unidiomatic in a language that also provides inverse tanh(). There’s the usual resort of dropping in I6 code, but that also has the usual complications in making I7 constructions visible to it.

3 Likes

Just curious, but does it start at the right and work backwards? Or consider addition to have high precedence?

2 Likes

Presumably it works from right to left, although I’m not sure if that’s guaranteed. There’s no mention of it in the documentation (that I could find, anyway; who knows what’s actually in there).

Use parentheses: (100 * 2) + 1

I don’t remember if this is documented or not.

1 Like

Sure, that works for a simple expression like that example, but putting parentheses around every operation in a long expression gets unreadable quickly, and separating them over multiple lines doesn’t help.

There’s this in the docs:

Something to be a little cautious of: brackets are used in equations to group terms together, and do not mean function application, as they would in a C-like programming language. For example, “sin(1+x)/2” takes the sine of “(1+x)/2”: if we want to halve the sine of “1+x”, we have to write “(sin(1+x))/2”.

(From 15.18)

I’m not sure if that’s on point or not, though, I’m having a little trouble parsing that.

2 Likes

@DeusIrae brings up a good point. If you’re using complex formulas, then it would be best to use the equations format as described in the section he cites (as opposed to inline calculations). Note that in this format, numerical precedence seems to behave as expected.

When play begins:
	let x be 2;
	let y be 1;
	let answer be given by answer = 100 * x + y where answer is a number;
	say answer.

Yields 201 as expected without the use of bracketing.

7 Likes

Thanks, that’s probably about as good as I’m going to get out of I7.

2 Likes

This is probably more useful syntax:

Equation - intfic's law
	a = 100 * x + y
where a, x, y are numbers.

When play begins:
	let x be 2;
	let y be 1;
	let a be given by intfic's law;
	say a.
1 Like

No, the original’s fine. Even though something like “let X be given by X = where X is a number” is unnecessarly verbose even by I7 standards, I don’t want to declare a separate block for each expression I use, especially one that’s declared away from the place I’m using it and pulling variables from some unspecified scope.

I know this is already solved, but I’ve been doing it one line at a time, just like if I were entering it on a calculator without a display:

let xdiff be x-coord of current minus x-coord of templight;
let ydiff be y-coord of current minus y-coord of templight;
if xdiff is 0:
	next;
let tempfrac be ydiff divided by xdiff;
let tempbear be resultantang;
let tempdeg be tempbear degrees;
let temptan be tangent of tempdeg;
let tempsin be sine of tempdeg;
let tempy be ydiff multiplied by tempsin;
let tempcos be cosine of tempdeg;
let tempx be xdiff multiplied by tempcos;
let tempsum be tempx plus tempy;
let tempdiff be temptan - tempfrac;
if tempdiff > 0:
	if tempdiff < 0.0001:
		now tempdiff is 0;
if tempdiff < 0:
	if tempdiff > -0.0001:
		now tempdiff is 0;
if tempdiff is 0:
	if tempsum < 0:
		decide on templight;
1 Like

I either use lots of parentheses or dip into Inform 6.

…but I also had missed that the given by syntax was usable without setting up an Equation!

3 Likes

I generally used @mathbrush’s solution, but now that @Zed mentioned using I6, I’d really recommend it, especially if you are confident in your programming abilities! I’d never considered it before.

I’ve gotten stung by the lack of parentheses many times. Often I feel putting line breaks in a long equation, when possible, makes it more readable.

Small tangent: this question and discussion helped me simplify one thing, where I’d been converting truth states to integers to see how many puzzles in one area had been covered. Example from Very Vile Fairy File:

to decide what number is boolval of (x - a truth state):
    if x is true, decide 1;
    decide 0;

to decide which number is buggin-score:
	decide on (boolval of sco-mean-muggin) + (boolval of sco-lean-luggin);

This can become

to decide which number is buggin-score:
    (- (+sco-mean-muggin+) + (+sco-lean-luggin+) -);

Not very profound stuff, but those handier with I6 than myself may look at this and say "oh, hey, I can do a lot more. And those less handy with I6 may find this works in a pinch. I’m not sure which way takes up more z-machine space or whatever.

this can be just:

to decide what number is boolval of (x - a truth state): (- {x} -).
1 Like