Page 1 of 1

Javascript arithmetic fun

Posted: Sat Oct 24, 2009 11:11 am
by Micha
Javascript doesn't know types - variables are whatever type makes sense at the time.

eg:

Code: Select all

var i = 1; // Number
var j = "1"; // String
var k = i + j; // "11" -> probably what wasn't expected.
The reason k contains "11" instead of 2 is that j is a string and Javascript ends up using string concatenation rather than arithmetic to compute the value for k.

To work around this, always use parseInt() when working with variables whose type you're not 100% sure of:

Code: Select all

var k = parseInt(i) + parseInt(j); // 2 -> probably what was expected.

This was the underlying reason for an odd bug whereby scooping sometimes filled my cargohold from a single barrel. The culprit was the new player.ship.manifest object and the way cargo is awarded using it.

eg:

Code: Select all

player.ship.manifest["food"] += 1; // Award 1 ton of Food
In this case though, the quantity was first retrieved from somewhere else, then printed as a string, before being awarded. Printing the quantity as a string converted it to a string type and then stuffed up the next calculation.

Code: Select all

var quantity = <something>;
player.consoleMessage(quantity + "<some string>");
player.ship.manifest["food"] += quantity; // WARNING
The fix is to either award the cargo before performing the string operation, or to make really sure, wrap quantity in parseInt:

Code: Select all

player.ship.manifest["food"] += parseInt(quantity); // Ok

Re: Javascript arithmetic fun

Posted: Sat Oct 24, 2009 12:12 pm
by JensAyton
Micha wrote:
To work around this, always use parseInt() when working with variables whose type you're not 100% sure of:

Code: Select all

var k = parseInt(i) + parseInt(j); // 2 -> probably what was expected.
…unless of course you wanted a floating-point value, in which case you want parseFloat() – or the unary + operator:

Code: Select all

var k = +i + +j;

Posted: Sat Oct 24, 2009 12:13 pm
by Eric Walch
Yes, this also irritates me sometimes, not being able to define your types. There are probably rules how additions are handled. Adding a number and a sting seems always to result in a string.

In your above example the quantity was already defined as a string in the original oxp were you got the example from. I did read the quantity in from shipdata.plist with

Code: Select all

var quantity = this.ship.scriptInfo.quantity;
However, quantity was defined there as string in my older versions. With the old awardCargo() this was never a problem so I never noticed this. For the new awarding method, the type must be correct. Changing the definition in the xml.plist as integer fixed it. Even printing that integer as part of a string kept its integer type intact.

Posted: Sat Oct 24, 2009 2:08 pm
by Kaks
In other words, the easiest way to modify the script would be to do the following:

Code: Select all

player.ship.manifest["food"] += +quantity;
though I must confess uneasiness when using the unary +, since it's normally indistingushable from the string concatenation +. If you're just as uneasy about it, an old & time honoured js 'trick' is to do

Code: Select all

player.ship.manifest["food"] += quantity-0;
instead.

Hope this helps :)

Posted: Sat Oct 24, 2009 4:25 pm
by JensAyton
When I design my Perfect Language™, it will have distinct operators for addition and concatenation. And probably for dot product and cross product, too. :-)