-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
num.dart
489 lines (449 loc) · 17.1 KB
/
num.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
// 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 ==(Object 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
* 123456789012345.toStringAsFixed(3); // 123456789012345.000
* 10000000000000000.toStringAsFixed(4); // 10000000000000000.0000
* 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.00e+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.negativeInfinity].
*
* 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).
*
* The [onError] parameter is deprecated and will be removed.
* Instead of `num.parse(string, (string) { ... })`,
* you should use `num.tryParse(string) ?? (...)`.
*/
static num parse(String input, [@deprecated num onError(String input)?]) {
num? result = tryParse(input);
if (result != null) return result;
if (onError == null) throw FormatException(input);
return onError(input);
}
/**
* Parses a string containing a number literal into a number.
*
* Like [parse] except that this function returns `null` for invalid inputs
* instead of throwing.
*/
static num? tryParse(String input) {
String source = input.trim();
// TODO(lrn): Optimize to detect format and result type in one check.
return int.tryParse(source) ?? double.tryParse(source);
}
}