blob: 06ecebe71a981c3ef0caeb614d844ecba07f678c [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart.core;
/**
* An integer or floating-point number.
*
* It is a compile-time error for any type other than [int] or [double]
* to attempt to extend or implement num.
*/
abstract class num implements Comparable<num> {
/**
* Test whether this value is numerically equal to `other`.
*
* If both operands are doubles, they are equal if they have the same
* representation, except that:
*
* * zero and minus zero (0.0 and -0.0) are considered equal. They
* both have the numerical value zero.
* * NaN is not equal to anything, including NaN. If either operand is
* NaN, the result is always false.
*
* If one operand is a double and the other is an int, they are equal if
* the double has an integer value (finite with no fractional part) and
* `identical(doubleValue.toInt(), intValue)` is true.
*
* If both operands are integers, they are equal if they have the same value.
*
* Returns false if `other` is not a [num].
*
* Notice that the behavior for NaN is non-reflexive. This means that
* equality of double values is not a proper equality relation, as is
* otherwise required of `operator==`. Using NaN in, e.g., a [HashSet]
* will fail to work. The behavior is the standard IEEE-754 equality of
* doubles.
*
* If you can avoid NaN values, the remaining doubles do have a proper
* equality relation, and can be used safely.
*
* Use [compareTo] for a comparison that distinguishes zero and minus zero,
* and that considers NaN values as equal.
*/
bool operator == (num other);
/**
* Returns a hash code for a numerical value.
*
* The hash code is compatible with equality. It returns the same value
* for an [int] and a [double] with the same numerical value, and therefore
* the same value for the doubles zero and minus zero.
*
* No guarantees are made about the hash code of NaN values.
*/
int get hashCode;
/**
* Compares this to `other`.
*
* Returns a negative number if `this` is less than `other`, zero if they are
* equal, and a positive number if `this` is greater than `other`.
*
* The ordering represented by this method is a total ordering of [num]
* values. All distinct doubles are non-equal, as are all distinct integers,
* but integers are equal to doubles if they have the same numerical
* value.
*
* For doubles, the `compareTo` operation is different from the partial
* ordering given by [operator==], [operator<] and [operator>]. For example,
* IEEE doubles impose that `0.0 == -0.0` and all comparison operations on
* NaN return false.
*
* This function imposes a complete ordering for doubles. When using
* `compareTo` the following properties hold:
*
* - All NaN values are considered equal, and greater than any numeric value.
* - -0.0 is less than 0.0 (and the integer 0), but greater than any non-zero
* negative value.
* - Negative infinity is less than all other values and positive infinity is
* greater than all non-NaN values.
* - All other values are compared using their numeric value.
*
* Examples:
* ```
* print(1.compareTo(2)); // => -1
* print(2.compareTo(1)); // => 1
* print(1.compareTo(1)); // => 0
*
* // The following comparisons yield different results than the
* // corresponding comparison operators.
* print((-0.0).compareTo(0.0)); // => -1
* print(double.NAN.compareTo(double.NAN)); // => 0
* print(double.INFINITY.compareTo(double.NAN)); // => -1
*
* // -0.0, and NaN comparison operators have rules imposed by the IEEE
* // standard.
* print(-0.0 == 0.0); // => true
* print(double.NAN == double.NAN); // => false
* print(double.INFINITY < double.NAN); // => false
* print(double.NAN < double.INFINITY); // => false
* print(double.NAN == double.INFINITY); // => false
*/
int compareTo(num other);
/** Addition operator. */
num operator +(num other);
/** Subtraction operator. */
num operator -(num other);
/** Multiplication operator. */
num operator *(num other);
/**
* Euclidean modulo operator.
*
* Returns the remainder of the euclidean division. The euclidean division of
* two integers `a` and `b` yields two integers `q` and `r` such that
* `a == b * q + r` and `0 <= r < b.abs()`.
*
* The euclidean division is only defined for integers, but can be easily
* extended to work with doubles. In that case `r` may have a non-integer
* value, but it still verifies `0 <= r < |b|`.
*
* The sign of the returned value `r` is always positive.
*
* See [remainder] for the remainder of the truncating division.
*/
num operator %(num other);
/** Division operator. */
double operator /(num other);
/**
* Truncating division operator.
*
* If either operand is a [double] then the result of the truncating division
* `a ~/ b` is equivalent to `(a / b).truncate().toInt()`.
*
* If both operands are [int]s then `a ~/ b` performs the truncating
* integer division.
*/
int operator ~/(num other);
/** Negate operator. */
num operator -();
/**
* Returns the remainder of the truncating division of `this` by [other].
*
* The result `r` of this operation satisfies:
* `this == (this ~/ other) * other + r`.
* As a consequence the remainder `r` has the same sign as the divider `this`.
*/
num remainder(num other);
/** Relational less than operator. */
bool operator <(num other);
/** Relational less than or equal operator. */
bool operator <=(num other);
/** Relational greater than operator. */
bool operator >(num other);
/** Relational greater than or equal operator. */
bool operator >=(num other);
/** True if the number is the double Not-a-Number value; otherwise, false. */
bool get isNaN;
/**
* True if the number is negative; otherwise, false.
*
* Negative numbers are those less than zero, and the double `-0.0`.
*/
bool get isNegative;
/**
* True if the number is positive infinity or negative infinity; otherwise,
* false.
*/
bool get isInfinite;
/**
* True if the number is finite; otherwise, false.
*
* The only non-finite numbers are NaN, positive infinity, and
* negative infinity.
*/
bool get isFinite;
/** Returns the absolute value of this [num]. */
num abs();
/**
* Returns minus one, zero or plus one depending on the sign and
* numerical value of the number.
*
* Returns minus one if the number is less than zero,
* plus one if the number is greater than zero,
* and zero if the number is equal to zero.
*
* Returns NaN if the number is the double NaN value.
*
* Returns a number of the same type as this number.
* For doubles, `-0.0.sign == -0.0`.
* The result satisfies:
*
* n == n.sign * n.abs()
*
* for all numbers `n` (except NaN, because NaN isn't `==` to itself).
*/
num get sign;
/**
* Returns the integer closest to `this`.
*
* Rounds away from zero when there is no closest integer:
* `(3.5).round() == 4` and `(-3.5).round() == -4`.
*
* If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
*/
int round();
/**
* Returns the greatest integer no greater than `this`.
*
* If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
*/
int floor();
/**
* Returns the least integer no smaller than `this`.
*
* If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
*/
int ceil();
/**
* Returns the integer obtained by discarding any fractional
* digits from `this`.
*
* If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
*/
int truncate();
/**
* Returns the double integer value closest to `this`.
*
* Rounds away from zero when there is no closest integer:
* `(3.5).roundToDouble() == 4` and `(-3.5).roundToDouble() == -4`.
*
* If this is already an integer valued double, including `-0.0`, or it is a
* non-finite double value, the value is returned unmodified.
*
* For the purpose of rounding, `-0.0` is considered to be below `0.0`,
* and `-0.0` is therefore considered closer to negative numbers than `0.0`.
* This means that for a value, `d` in the range `-0.5 < d < 0.0`,
* the result is `-0.0`.
*
* The result is always a double.
* If this is a numerically large integer, the result may be an infinite
* double.
*/
double roundToDouble();
/**
* Returns the greatest double integer value no greater than `this`.
*
* If this is already an integer valued double, including `-0.0`, or it is a
* non-finite double value, the value is returned unmodified.
*
* For the purpose of rounding, `-0.0` is considered to be below `0.0`.
* A number `d` in the range `0.0 < d < 1.0` will return `0.0`.
*
* The result is always a double.
* If this is a numerically large integer, the result may be an infinite
* double.
*/
double floorToDouble();
/**
* Returns the least double integer value no smaller than `this`.
*
* If this is already an integer valued double, including `-0.0`, or it is a
* non-finite double value, the value is returned unmodified.
*
* For the purpose of rounding, `-0.0` is considered to be below `0.0`.
* A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`.
*
* The result is always a double.
* If this is a numerically large integer, the result may be an infinite
* double.
*/
double ceilToDouble();
/**
* Returns the double integer value obtained by discarding any fractional
* digits from the double value of `this`.
*
* If this is already an integer valued double, including `-0.0`, or it is a
* non-finite double value, the value is returned unmodified.
*
* For the purpose of rounding, `-0.0` is considered to be below `0.0`.
* A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and
* in the range `0.0 < d < 1.0` it will return 0.0.
*
* The result is always a double.
* If this is a numerically large integer, the result may be an infinite
* double.
*/
double truncateToDouble();
/**
* Returns this [num] clamped to be in the range [lowerLimit]-[upperLimit].
*
* The comparison is done using [compareTo] and therefore takes `-0.0` into
* account. This also implies that [double.NAN] is treated as the maximal
* double value.
*
* The arguments [lowerLimit] and [upperLimit] must form a valid range where
* `lowerLimit.compareTo(upperLimit) <= 0`.
*/
num clamp(num lowerLimit, num upperLimit);
/** Truncates this [num] to an integer and returns the result as an [int]. */
int toInt();
/**
* Return this [num] as a [double].
*
* If the number is not representable as a [double], an
* approximation is returned. For numerically large integers, the
* approximation may be infinite.
*/
double toDouble();
/**
* Returns a decimal-point string-representation of `this`.
*
* Converts `this` to a [double] before computing the string representation.
*
* If the absolute value of `this` is greater or equal to `10^21` then this
* methods returns an exponential representation computed by
* `this.toStringAsExponential()`. Otherwise the result
* is the closest string representation with exactly [fractionDigits] digits
* after the decimal point. If [fractionDigits] equals 0 then the decimal
* point is omitted.
*
* The parameter [fractionDigits] must be an integer satisfying:
* `0 <= fractionDigits <= 20`.
*
* Examples:
*
* 1.toStringAsFixed(3); // 1.000
* (4321.12345678).toStringAsFixed(3); // 4321.123
* (4321.12345678).toStringAsFixed(5); // 4321.12346
* 123456789012345678901.toStringAsFixed(3); // 123456789012345683968.000
* 1000000000000000000000.toStringAsFixed(3); // 1e+21
* 5.25.toStringAsFixed(0); // 5
*/
String toStringAsFixed(int fractionDigits);
/**
* Returns an exponential string-representation of `this`.
*
* Converts `this` to a [double] before computing the string representation.
*
* If [fractionDigits] is given then it must be an integer satisfying:
* `0 <= fractionDigits <= 20`. In this case the string contains exactly
* [fractionDigits] after the decimal point. Otherwise, without the parameter,
* the returned string uses the shortest number of digits that accurately
* represent [this].
*
* If [fractionDigits] equals 0 then the decimal point is omitted.
* Examples:
*
* 1.toStringAsExponential(); // 1e+0
* 1.toStringAsExponential(3); // 1.000e+0
* 123456.toStringAsExponential(); // 1.23456e+5
* 123456.toStringAsExponential(3); // 1.235e+5
* 123.toStringAsExponential(0); // 1e+2
*/
String toStringAsExponential([int fractionDigits]);
/**
* Converts `this` to a double and returns a string representation with
* exactly [precision] significant digits.
*
* The parameter [precision] must be an integer satisfying:
* `1 <= precision <= 21`.
*
* Examples:
*
* 1.toStringAsPrecision(2); // 1.0
* 1e15.toStringAsPrecision(3); // 1.00+15
* 1234567.toStringAsPrecision(3); // 1.23e+6
* 1234567.toStringAsPrecision(9); // 1234567.00
* 12345678901234567890.toStringAsPrecision(20); // 12345678901234567168
* 12345678901234567890.toStringAsPrecision(14); // 1.2345678901235e+19
* 0.00000012345.toStringAsPrecision(15); // 1.23450000000000e-7
* 0.0000012345.toStringAsPrecision(15); // 0.00000123450000000000
*/
String toStringAsPrecision(int precision);
/**
* Returns the shortest string that correctly represent the input number.
*
* All [double]s in the range `10^-6` (inclusive) to `10^21` (exclusive)
* are converted to their decimal representation with at least one digit
* after the decimal point. For all other doubles,
* except for special values like `NaN` or `Infinity`, this method returns an
* exponential representation (see [toStringAsExponential]).
*
* Returns `"NaN"` for [double.NAN], `"Infinity"` for [double.INFINITY], and
* `"-Infinity"` for [double.MINUS_INFINITY].
*
* An [int] is converted to a decimal representation with no decimal point.
*
* Examples:
*
* (0.000001).toString(); // "0.000001"
* (0.0000001).toString(); // "1e-7"
* (111111111111111111111.0).toString(); // "111111111111111110000.0"
* (100000000000000000000.0).toString(); // "100000000000000000000.0"
* (1000000000000000000000.0).toString(); // "1e+21"
* (1111111111111111111111.0).toString(); // "1.1111111111111111e+21"
* 1.toString(); // "1"
* 111111111111111111111.toString(); // "111111111111111110000"
* 100000000000000000000.toString(); // "100000000000000000000"
* 1000000000000000000000.toString(); // "1000000000000000000000"
* 1111111111111111111111.toString(); // "1111111111111111111111"
* 1.234e5.toString(); // 123400
* 1234.5e6.toString(); // 1234500000
* 12.345e67.toString(); // 1.2345e+68
*
* Note: the conversion may round the output if the returned string
* is accurate enough to uniquely identify the input-number.
* For example the most precise representation of the [double] `9e59` equals
* `"899999999999999918767229449717619953810131273674690656206848"`, but
* this method returns the shorter (but still uniquely identifying) `"9e59"`.
*
*/
String toString();
/**
* Parses a string containing a number literal into a number.
*
* The method first tries to read the [input] as integer (similar to
* [int.parse] without a radix).
* If that fails, it tries to parse the [input] as a double (similar to
* [double.parse]).
* If that fails, too, it invokes [onError] with [input], and the result
* of that invocation becomes the result of calling `parse`.
*
* If no [onError] is supplied, it defaults to a function that throws a
* [FormatException].
*
* For any number `n`, this function satisfies
* `identical(n, num.parse(n.toString()))` (except when `n` is a NaN `double`
* with a payload).
*/
static num parse(String input, [num onError(String input)]) {
String source = input.trim();
// TODO(lrn): Optimize to detect format and result type in one check.
num result = int.parse(source, onError: _returnIntNull);
if (result != null) return result;
result = double.parse(source, _returnDoubleNull);
if (result != null) return result;
if (onError == null) throw new FormatException(input);
return onError(input);
}
/** Helper functions for [parse]. */
static int _returnIntNull(String _) => null;
static double _returnDoubleNull(String _) => null;
}