Numbers in Dart
(This is part 10 in an ongoing series about Dart. Check out part 9, a Dart SDK quick tour.)
Intro
It's time to look at numbers in Dart. Wait, where are you going? Come back, numbers are cool! This will be interesting, for reals. I can at least promise this will be easy and quick, for numbers in Dart aren't complicated. If you're compiling to JavaScript, though, there are a few edge cases (bugs?) so I encourage you to not skip this episode.
The Basics
Like everything else in Dart, numbers are objects. In fact, numbers are specified as interfaces.
Numbers come in two flavors in Dart: integers of arbitrary size and decimal 64 bit doubles as specified by the IEEE 754 standard. Both int and double are subinterfaces of num.
The num interface defines the basics like +, -, /, and *. Num is where you'll also find abs(), ceil(), and floor(), among other methods.
Int
Integers are numbers without a decimal point. For example:
You may also specify hexadecimals with the 0x prefix.
Alert: the last line in the above sample, the result is different between the Dart VM and Dart compiled to JavaScript. I've opened a bug to see if this is by design.
Integers can be of arbitrary precision. For example:
While the above will work in the Dart VM, when compiled to JavaScript, the large number becomes Infinity.
Alert: JavaScript only supports +/- 9007199254740992 for integers and (at least in V8) 1.7976931348623157e+308 for Number.MAX_VALUE. I've opened a bug to discuss this, as the above code functions differently in Dart VM and JavaScript.
You might see Dart code that explicitly adds a + prefix to the number, though it isn't necessary.
Double
If the number includes a decimal, it is a 64 bit double that follows IEEE 754 standard.
A simple example:
Exponent notation is supported:
Here again you can see slight differences between what Dart VM and JavaScript will do. The generated JavaScript code looks like this:
NaN
Dividing zero by zero will result in "not a number" in Dart, similar to JavaScript but unlike Java.
The num interface provides a simple check for isNaN().
Converting to and from a String
A common requirement is to turn a number into a String, or a String into a number.
Parsing a String to an int uses the Math class:
Parsing a String into a double is similar:
Attempting to format a string that isn't a number will throw a BadNumberFormatException.
Going the other way, converting numbers to Strings, is also very easy thanks to toString().
For doubles, toStringAsFixed(int fractionDigits) will truncate the decimal digits:
Misc methods
A potentially unfamiliar change is the methods like ceil() and abs() are found on the num interface, and not in Math.
Bit manipulating
The num interface also specifies the traditional bit shifting, and'ing, and or'ing. Some simple examples:
Summary
Dart supplies a num interface with two subinterfaces: int and double. Integers are arbitrary precision, meaning they have arbitrary size. Doubles are 64 bit decimals that follow IEEE 754 spec.
Generally speaking, numbers function the same across native Dart and Dart compiled to JavaScript, but there are some subtle differences. For example, watch out for very large numbers and checking the difference between int and double in JavaScript (currently everything is checked against number in JavaScript from the Frog compiler.)
Next Steps
Read more of my Dart posts, try Dart in your browser, browse the API docs, or file an issue request. Dart is getting ready, please send us your feedback!
Intro
It's time to look at numbers in Dart. Wait, where are you going? Come back, numbers are cool! This will be interesting, for reals. I can at least promise this will be easy and quick, for numbers in Dart aren't complicated. If you're compiling to JavaScript, though, there are a few edge cases (bugs?) so I encourage you to not skip this episode.
The Basics
Like everything else in Dart, numbers are objects. In fact, numbers are specified as interfaces.
Numbers come in two flavors in Dart: integers of arbitrary size and decimal 64 bit doubles as specified by the IEEE 754 standard. Both int and double are subinterfaces of num.
num is the supertype, int and double extend num. |
Int
Integers are numbers without a decimal point. For example:
var x = 1;
print(x);
print(x is num); // true in both Dart VM and JS
print(x is int); // true in both Dart VM and JS
You may also specify hexadecimals with the 0x prefix.
var hex = 0xDEADBEEF;
print(hex); // 873735928559
print(hex is num); // true in both Dart VM and JS
print(hex is int); // true in both Dart VM and JS
print(hex is! double); // true in Dart VM, FALSE when compiled to JavaScript
Alert: the last line in the above sample, the result is different between the Dart VM and Dart compiled to JavaScript. I've opened a bug to see if this is by design.
Integers can be of arbitrary precision. For example:
var bigInt = 346538465234590347592847298346243459756895347698465298346583746592374652378462347569234765834765947569827346583465243765923847659234765928347659567398475647495873984572947593470294387093493456870849216348723763945678236420938467345762304958724596873045876234572037862934765294365243652548673456705673465273465246734506873456729457623845623456234650457693475603768922346728346256;
print(bigInt); // correct in Dart VM, Infinity when compiled to JavaScript
print(bigInt is num); // true in both Dart VM and JS
print(bigInt is int); // true in both Dart VM and JS
While the above will work in the Dart VM, when compiled to JavaScript, the large number becomes Infinity.
Alert: JavaScript only supports +/- 9007199254740992 for integers and (at least in V8) 1.7976931348623157e+308 for Number.MAX_VALUE. I've opened a bug to discuss this, as the above code functions differently in Dart VM and JavaScript.
You might see Dart code that explicitly adds a + prefix to the number, though it isn't necessary.
var positive = +12345;
print(positive); // 12345
print(positive is num); // true
print(positive is int); // true
Double
If the number includes a decimal, it is a 64 bit double that follows IEEE 754 standard.
A simple example:
var y = 1.1;
print(y);
print(y is num); // true in both Dart VM and JS
print(y is double); // true in both Dart VM and JS
Exponent notation is supported:
var exponents = 1.42e5;
print(exponents); // prints 142000.0 in Dart VM, 142000 when compiled to JavaScript
print(exponents is num); // true in both Dart VM and JS
print(exponents is! int); // true in Dart VM, FALSE when compiled to JS
print(exponents is double); // true in both Dart VM and JS
Here again you can see slight differences between what Dart VM and JavaScript will do. The generated JavaScript code looks like this:
// generated JavaScript from Frog, as of 2012-02-04
var exponents = (142000.0);
print(exponents);
print((typeof(exponents) == 'number'));
print((typeof(exponents) != 'number')); // this is FALSE, see corresponding Dart code above
print((typeof(exponents) == 'number'));
NaN
Dividing zero by zero will result in "not a number" in Dart, similar to JavaScript but unlike Java.
The num interface provides a simple check for isNaN().
var nan = 0 / 0;
print(nan.isNaN()); // true in both Dart VM and JS
Converting to and from a String
A common requirement is to turn a number into a String, or a String into a number.
Parsing a String to an int uses the Math class:
var one = Math.parseInt("1");
print(one); // 1
print(one is int); // true
Parsing a String into a double is similar:
var onePointOne = Math.parseDouble("1.1");
print(onePointOne); // 1.1
print(onePointOne is double); // true
Attempting to format a string that isn't a number will throw a BadNumberFormatException.
try {
var gook = Math.parseInt("foo");
} catch(BadNumberFormatException e) {
print(e); // BadNumberFormatException: 'foo'
}
Going the other way, converting numbers to Strings, is also very easy thanks to toString().
String oneAsString = 1.toString();
print(oneAsString); // 1
print(oneAsString is String);
For doubles, toStringAsFixed(int fractionDigits) will truncate the decimal digits:
print(3.14159.toStringAsFixed(2)); // 3.14
Misc methods
A potentially unfamiliar change is the methods like ceil() and abs() are found on the num interface, and not in Math.
// absolute value is a method on num
print((-4).abs() == 4);
// ceil and floor are also methods on num
print(3.25.ceil() == 4.0);
print(3.25.floor() == 3.0);
// round will round up if .5 or greater, otherwise will round down
print(3.25.round() == 3);
print(3.89.round() == 4);
print(3.5.round() == 4);
print(3.49.round() == 3);
// truncates the decimal digits
print(3.24532.truncate() == 3.0);
// convert a double to an int
print(3.24.toInt() == 3);
Bit manipulating
The num interface also specifies the traditional bit shifting, and'ing, and or'ing. Some simple examples:
print(3<<1 == 6); // 0011 << 1 == 0110
print(3>>1 == 1); // 0011 >> 1 == 0001
print((3|4) == 7); // 0011 | 0100 == 0111
Summary
Dart supplies a num interface with two subinterfaces: int and double. Integers are arbitrary precision, meaning they have arbitrary size. Doubles are 64 bit decimals that follow IEEE 754 spec.
Generally speaking, numbers function the same across native Dart and Dart compiled to JavaScript, but there are some subtle differences. For example, watch out for very large numbers and checking the difference between int and double in JavaScript (currently everything is checked against number in JavaScript from the Frog compiler.)
Next Steps
Read more of my Dart posts, try Dart in your browser, browse the API docs, or file an issue request. Dart is getting ready, please send us your feedback!