Dart Programming Fundamentals

Numbers, Booleans & Type Conversion

35 min Lesson 4 of 6

Numbers in Dart

Dart has three numeric types that form a hierarchy: num is the parent type, with int and double as its children. Understanding when to use each type is essential for writing correct and efficient Dart code.

The Number Type Hierarchy

// num is the parent of both int and double
num anyNumber = 42;      // can hold int
anyNumber = 3.14;        // can also hold double

int wholeNumber = 42;    // only whole numbers
double decimalNumber = 3.14; // only decimal numbers

Integers (int)

Integers represent whole numbers without a decimal point. On native platforms (mobile, desktop), Dart integers are 64-bit signed values, giving a range from about -9.2 quintillion to 9.2 quintillion. On the web (compiled to JavaScript), they follow JavaScript’s number precision.

Working with Integers

void main() {
  int age = 28;
  int negative = -100;
  int zero = 0;

  // Different integer literal formats
  int decimal = 255;
  int hex = 0xFF;          // 255 in hexadecimal
  int binary = 0b11111111; // 255 in binary (Dart 3+)

  print(decimal == hex);   // true
  print(hex == binary);    // true

  // Large numbers with underscore separators for readability
  int population = 7_900_000_000;
  int bytes = 1_073_741_824;
  print(population);  // 7900000000
  print(bytes);       // 1073741824
}
Pro Tip: Use underscores (_) in large numbers to improve readability. Dart ignores them completely -- 1_000_000 is exactly the same as 1000000.

Doubles (double)

Doubles represent 64-bit floating-point numbers following the IEEE 754 standard. They can hold fractional values, very large numbers, and very small numbers using scientific notation.

Working with Doubles

void main() {
  double pi = 3.14159265;
  double price = 29.99;
  double tiny = 0.001;
  double negative = -273.15;

  // Scientific notation
  double speed = 3.0e8;     // 300,000,000 (speed of light m/s)
  double small = 1.6e-19;   // 0.00000000000000000016

  print(speed);  // 300000000.0
  print(small);  // 1.6e-19

  // Integer assigned to double automatically becomes double
  double value = 42;  // stored as 42.0
  print(value);        // 42.0
}
Warning: Floating-point arithmetic can produce unexpected results due to how computers represent decimal numbers in binary. For example, 0.1 + 0.2 equals 0.30000000000000004, not 0.3. For financial calculations, consider working with integers (cents instead of dollars) or using a decimal library.

Useful Number Properties and Methods

Number Properties

void main() {
  int number = -42;
  double decimal = 3.7;

  // Properties
  print(number.isNegative);   // true
  print(number.isEven);       // true
  print(number.isOdd);        // false
  print(decimal.isFinite);    // true
  print(decimal.isInfinite);  // false
  print(decimal.isNaN);       // false

  // Special double values
  print(double.infinity);     // Infinity
  print(double.negativeInfinity); // -Infinity
  print(double.nan);          // NaN
  print(double.maxFinite);    // 1.7976931348623157e+308
}

Number Methods

void main() {
  double value = 3.7;

  // Rounding
  print(value.round());       // 4 (nearest integer)
  print(value.floor());       // 3 (round down)
  print(value.ceil());        // 4 (round up)
  print(value.truncate());    // 3 (remove decimal part)

  // Absolute value
  print((-42).abs());         // 42
  print((-3.14).abs());       // 3.14

  // Clamp to a range
  int score = 150;
  print(score.clamp(0, 100)); // 100 (clamped to max)

  int low = -10;
  print(low.clamp(0, 100));   // 0 (clamped to min)

  // Formatting doubles
  double pi = 3.14159265;
  print(pi.toStringAsFixed(2));       // 3.14
  print(pi.toStringAsPrecision(4));   // 3.142
}

Arithmetic Operators

Dart supports all standard arithmetic operators:

Basic Arithmetic

void main() {
  int a = 10;
  int b = 3;

  print(a + b);   // 13  (addition)
  print(a - b);   // 7   (subtraction)
  print(a * b);   // 30  (multiplication)
  print(a / b);   // 3.3333... (division -- always returns double)
  print(a ~/ b);  // 3   (integer division -- truncates)
  print(a % b);   // 1   (modulo -- remainder)

  // Unary operators
  int c = 5;
  print(-c);      // -5  (negate)
}
Note: The regular division operator / always returns a double in Dart, even when dividing two integers. Use ~/ (truncating division) when you want an integer result.

The dart:math Library

For advanced mathematical operations, import the dart:math library:

Using dart:math

import 'dart:math';

void main() {
  // Constants
  print(pi);          // 3.141592653589793
  print(e);           // 2.718281828459045

  // Power and square root
  print(pow(2, 10));  // 1024 (2^10)
  print(sqrt(144));   // 12.0

  // Min and max
  print(min(5, 10));  // 5
  print(max(5, 10));  // 10

  // Logarithm
  print(log(e));      // 1.0

  // Random numbers
  var random = Random();
  print(random.nextInt(100));    // 0-99
  print(random.nextDouble());   // 0.0-1.0
  print(random.nextBool());     // true or false
}

Booleans (bool)

The bool type has exactly two values: true and false. Unlike JavaScript, Dart does not have truthy and falsy values. Only actual bool values can be used in conditions.

Boolean Basics

void main() {
  bool isActive = true;
  bool isAdmin = false;

  // Direct use in conditions
  if (isActive) {
    print('User is active');
  }

  // Dart does NOT have truthy/falsy like JavaScript
  // if (1) { ... }       // ERROR! 1 is not a bool
  // if ('hello') { ... } // ERROR! String is not a bool
  // if (null) { ... }    // ERROR! null is not a bool

  // You must explicitly compare
  int count = 5;
  if (count > 0) {       // This works -- comparison returns bool
    print('Has items');
  }
}
Important: If you come from JavaScript, remember that Dart is strict about booleans. There is no implicit conversion of 0, "", null, or undefined to false. You must always use explicit boolean expressions in conditions.

Logical Operators

Boolean Logic

void main() {
  bool a = true;
  bool b = false;

  // AND -- both must be true
  print(a && b);   // false
  print(a && a);   // true

  // OR -- at least one must be true
  print(a || b);   // true
  print(b || b);   // false

  // NOT -- inverts the value
  print(!a);       // false
  print(!b);       // true

  // Practical example
  int age = 25;
  bool hasLicense = true;

  bool canDrive = age >= 18 && hasLicense;
  print('Can drive: \$canDrive');  // Can drive: true
}

Comparison Operators

Comparison operators return boolean values and are used extensively in conditions:

All Comparison Operators

void main() {
  int x = 10;
  int y = 20;

  print(x == y);   // false (equal)
  print(x != y);   // true  (not equal)
  print(x > y);    // false (greater than)
  print(x < y);    // true  (less than)
  print(x >= 10);  // true  (greater or equal)
  print(x <= 20);  // true  (less or equal)

  // Chaining comparisons
  int score = 75;
  bool passed = score >= 60 && score <= 100;
  print('Passed: \$passed');  // Passed: true
}

Type Conversion

Converting between types is a common task in Dart. Here are all the important conversions you need to know:

Between Number Types

int and double Conversion

void main() {
  // int to double
  int whole = 42;
  double asDouble = whole.toDouble();
  print(asDouble);       // 42.0

  // double to int (truncates decimal part)
  double decimal = 9.99;
  int asInt = decimal.toInt();
  print(asInt);          // 9 (not rounded!)

  // double to int (rounded)
  int rounded = decimal.round();
  print(rounded);        // 10

  // Safe: int can always become double
  // Careful: double to int loses precision
}

Numbers to Strings

Number to String

void main() {
  int count = 42;
  double price = 9.99;

  // Basic conversion
  String countStr = count.toString();
  String priceStr = price.toString();
  print(countStr);  // '42'
  print(priceStr);  // '9.99'

  // Formatted conversion
  print(price.toStringAsFixed(1));      // '10.0'
  print(price.toStringAsFixed(3));      // '9.990'
  print(12345.toStringAsExponential()); // '1.2345e+4'

  // Using string interpolation (auto-converts)
  print('Count: \$count, Price: \$price');
}

Strings to Numbers

String to Number (Safe vs Unsafe)

void main() {
  // UNSAFE -- throws FormatException on invalid input
  int a = int.parse('42');
  double b = double.parse('3.14');
  print(a);  // 42
  print(b);  // 3.14

  // SAFE -- returns null on invalid input
  int? c = int.tryParse('abc');
  double? d = double.tryParse('xyz');
  print(c);  // null
  print(d);  // null

  // Pattern: tryParse with fallback
  String userInput = 'not a number';
  int value = int.tryParse(userInput) ?? 0;
  print(value);  // 0 (fallback used)

  // Parse hex string
  int hex = int.parse('FF', radix: 16);
  print(hex);  // 255
}

Boolean Conversions

Boolean to/from Other Types

void main() {
  // Bool to String
  bool active = true;
  String activeStr = active.toString();
  print(activeStr);  // 'true'

  // String to Bool (no built-in parse, do it manually)
  String input = 'true';
  bool parsed = input.toLowerCase() == 'true';
  print(parsed);  // true

  // Common pattern: number to bool
  int status = 1;
  bool isActive = status == 1;
  print(isActive);  // true

  // Bool to int
  bool flag = true;
  int flagInt = flag ? 1 : 0;
  print(flagInt);  // 1
}

The Null-Aware Operators

When working with type conversions, values can often be null. Dart provides null-aware operators to handle this elegantly:

Null-Aware Operators with Conversions

void main() {
  // ?? -- provide default if null
  int? parsed = int.tryParse('abc');
  int value = parsed ?? 0;
  print(value);  // 0

  // Shorthand in one line
  int age = int.tryParse('25') ?? 0;
  print(age);  // 25

  int invalid = int.tryParse('hello') ?? -1;
  print(invalid);  // -1
}

Practical Example: Building a Calculator

Mini Calculator

import 'dart:math';

void main() {
  double a = 15.0;
  double b = 4.0;

  print('--- Calculator ---');
  print('\$a + \$b = ${a + b}');           // 19.0
  print('\$a - \$b = ${a - b}');           // 11.0
  print('\$a * \$b = ${a * b}');           // 60.0
  print('\$a / \$b = ${(a / b).toStringAsFixed(2)}'); // 3.75
  print('\$a % \$b = ${a % b}');           // 3.0
  print('\$a ^ \$b = ${pow(a, b)}');       // 50625.0
  print('sqrt(\$a) = ${sqrt(a).toStringAsFixed(4)}'); // 3.8730

  // Is the result a whole number?
  double result = a / b;
  bool isWhole = result == result.roundToDouble();
  print('Is \$a/\$b a whole number? \$isWhole'); // false
}

Practice Exercise

Open DartPad and create a program that: (1) Declares two integer variables and two double variables. (2) Performs all arithmetic operations (+, -, *, /, ~/, %) and prints the results. (3) Uses dart:math to calculate the square root and power of a number. (4) Converts a double price to an integer using round(), floor(), and ceil() and compares the results. (5) Uses tryParse with the ?? operator to safely convert a string to a number with a fallback value.