Chapter 3 Readings: 3.3 Numeric Data Types and Variables

Numeric Data Types and Variables

Variables of the string data type are used to store text, but they cannot store numeric data for the purpose of performing mathematical operations. To store numbers and perform mathematical calculations on them, a numeric data type must be used. C# provides several primitive data types for specialized and general purposes.

The three primary primitive numeric data types used for most general programming tasks are int, double, and decimal.

Primary Primitive Numeric Data Types

1. int Data Type
  • Description: Holds whole numbers (integers) only. Examples of valid int values include 4242, 00, and 99-99. An int variable cannot hold numbers with fractional parts, such as 22.122.1 or 4.9-4.9.

  • Primary Purpose: Primary data type for storing and working with whole numbers.

  • Memory Allocation: Uses 3232 bits of memory.

  • Value Range: 2,147,483,648-2,147,483,648 through 2,147,483,6472,147,483,647.

2. double Data Type
  • Description: Holds real numbers (numbers that may contain fractional parts), such as 3.53.5, 87.95-87.95, or 3.03.0.

  • Precision: Stored numbers are rounded to 1515 digits of precision.

  • Format: Stored in double precision floating-point notation.

  • Primary Purpose: Used for storing any real number that might have a fractional part, and particularly useful for extremely large or extremely small numbers.

  • Memory Allocation: Uses 6464 bits of memory.

  • Value Range: ±5.0×102324\pm 5.0 \times 10^{2324} to ±1.7×10308\pm 1.7 \times 10^{308} (representing ±5.0×10324\pm 5.0 \times 10^{-324} to ±1.7×10308\pm 1.7 \times 10^{308}).

3. decimal Data Type
  • Description: Holds real numbers with significantly greater precision than the double data type.

  • Precision: Stored numbers are rounded to 2828 digits of precision.

  • Format: Stored in decimal notation.

  • Primary Purpose: Most commonly used in financial applications and for storing monetary amounts due to its high precision.

  • Memory Allocation: Uses 128128 bits of memory.

  • Value Range: ±1.0×10228\pm 1.0 \times 10^{228} to ±7.9×1028\pm 7.9 \times 10^{28} (representing ±1.0×1028\pm 1.0 \times 10^{-28} to ±7.9×1028\pm 7.9 \times 10^{28}).

Variable Declarations

Declaring a numeric variable requires specifying the data type followed by the variable name:

int speed;
double distance;
decimal grossPay;
  • int speed; declares an int variable named speed.

  • double distance; declares a double variable named distance.

  • decimal grossPay; declares a decimal variable named grossPay.

Numeric Literals

A literal is a piece of data written directly into a program's code. When a specific value is known at the time of writing code, it can be assigned as a literal to a variable. A numeric literal is a number written into the program's code.

Examples:

int hoursWorked = 40;
double temperature = 87.6;

In these statements, 4040 and 87.687.6 are numeric literals.

Types of Numeric Literals

Integer Literals

When a numeric literal is written without a decimal point and fits within the range of an int (2,147,483,648-2,147,483,648 to 2,147,483,6472,147,483,647), C# treats it as an int. This is referred to as an integer literal.

Examples:

int hoursWorked = 40;
int unitsSold = 650;
int score = -23;
Double Literals

When a numeric literal is written with a decimal point and fits within the range of a double, C# treats it as a double. This is referred to as a double literal.

Examples:

double distance = 28.75;
double speed = 87.3;
double temperature = -10.0;
Decimal Literals

To specify that a numeric literal is of the decimal data type, the letter M or m must be appended to the end of the literal.

Examples:

decimal payRate = 28.75m;
decimal price = 8.95M;
decimal profit = -50m;

Memory Tip: Remembering that "m" stands for "money" serves as a useful mnemonic that decimal literals must end with M or m.

Assignment Compatibility Rules

C# enforces strict assignment compatibility rules between different numeric data types to prevent unintentional data loss or range overflow errors.

Assignment Compatibility for int Variables

  • Allowed: int values can be assigned to int variables.

  • Not Allowed: double or decimal values cannot be assigned to int variables.

Examples:
int hoursWorked = 40;   // Valid: int assigned to int
int unitsSold = 650m;   // ERROR: Cannot assign decimal to int
int score = -25.5;      // ERROR: Cannot assign double to int
Reasons for Prohibition:
  1. Fractional Data Loss: double and decimal data types can store fractional values, whereas int variables can only store whole numbers. Storing fractional values in an int would require discarding the fractional portion.

  2. Range Overflow/Underflow: double and decimal values can represent numbers substantially larger or smaller than the allowed range of an int variable (2,147,483,648-2,147,483,648 to 2,147,483,6472,147,483,647).

Assignment Compatibility for double Variables

  • Allowed: double or int values can be assigned to double variables.

  • Not Allowed: decimal values cannot be assigned to double variables.

Examples:
double distance = 28.75;  // Valid: double assigned to double
double speed = 75;        // Valid: int assigned to double (implicitly converted)
double sales = 6500.0m;   // ERROR: Cannot assign decimal to double
Explanation:
  • Assigning an int to a double is permitted because any value storable in an int can be converted to a double with no loss of data. The implicit conversion happens automatically.

  • Assigning a decimal to a double is prohibited because decimal provides up to 2828 digits of precision, whereas double provides only 1515 digits of precision. Converting a decimal to a double could result in precision loss.

Assignment Compatibility for decimal Variables

  • Allowed: decimal or int values can be assigned to decimal variables.

  • Not Allowed: double values cannot be assigned to decimal variables.

Examples:
decimal balance = 9280.73m; // Valid: decimal assigned to decimal
decimal price = 50;         // Valid: int assigned to decimal (implicitly converted)
decimal sales = 6500.0;     // ERROR: Cannot assign double to decimal
Explanation:
  • Assigning an int to a decimal is permitted via implicit conversion without data loss.

  • Assigning a double to a decimal is prohibited because a double value can potentially be much larger or smaller than the allowed range of a decimal variable.

Explicit Type Conversion with Cast Operators

When an explicit conversion is required between non-compatible data types (such as assigning a double to an int), a cast operator can be used to override default compiler restrictions.

Syntax and Operation

A cast operator consists of the target data type name enclosed in parentheses (DataType) placed directly to the left of the expression or variable to be converted.

1 // Declare an int variable.
2 int wholeNumber;
3 
4 // Declare a double variable.
5 double realNumber = 3.0;
6 
7 // Assign the double to the int.
8 wholeNumber = (int)realNumber;
  • Line 2: Declares wholeNumber as an int.

  • Line 5: Declares realNumber as a double initialized with 3.03.0.

  • Line 8: Uses the (int) cast operator to convert the value of realNumber to an int and stores 33 in wholeNumber.

Cast Operator Code Examples

Code Example

Description

int wholeNumber;
decimal moneyNumber = 4500m;
wholeNumber = (int)moneyNumber;

The (int) cast operator converts the value of the moneyNumber variable to an int. The converted value is assigned to the wholeNumber variable.

double realNumber;
decimal moneyNumber = 625.70m;
realNumber = (double)moneyNumber;

The (double) cast operator converts the value of the moneyNumber variable to a double. The converted value is assigned to the realNumber variable.

decimal moneyNumber;
double realNumber = 98.9;
moneyNumber = (decimal)realNumber;

The (decimal) cast operator converts the value of the realNumber variable to a decimal. The converted value is assigned to the moneyNumber variable.

Truncation and Variable Immutability

  • Truncation: When converting a floating-point or decimal value containing a fractional part to an integer using a cast operator, any digits following the decimal point are completely dropped. This process is called truncation.

int wholeNumber;
double realNumber = 8.9;
wholeNumber = (int)realNumber;

After execution of this code, wholeNumber contains 88 because the fractional component .9.9 is dropped.

  • Immutability of Original Variables: Applying a cast operator to a variable does not alter the original variable's stored value. The operator merely extracts and converts the value for the expression. In the example above, realNumber retains its original value of 8.98.9.

Declaring Local Variables with the var Keyword

C# allows local variables to be declared using the var keyword in place of an explicit data type name.

Type Inference Mechanism

When var is used, the compiler automatically infers the variable's data type based on the initialization value provided.

var amount = 100;
var interestRate = 12.0;
var stockCode = "D465U";
var accountBalance = 1000.0m;
  • amount is inferred as int because 100100 is an integer literal.

  • interestRate is inferred as double because 12.012.0 is a double literal.

  • stockCode is inferred as string because "D465U" is a string literal.

  • accountBalance is inferred as decimal because 1000.0m1000.0m is a decimal literal.

Rules and Restrictions for var

  1. Initialization Required: A variable declared with var must be initialized in the same statement so the compiler can infer its type.

   var myvalue; // ERROR! Compiler cannot infer type without an initial value
   ```
2. **Single Variable Declarations Only:** Multiple variables cannot be declared in a single statement using `var`.

csharp var x, y, z = 99; // ERROR! Multiple variable declarations not permitted with var    ```

Purpose of var

The var keyword is intended to simplify syntactically complex declaration statements and enhance overall code readability in advanced scenarios.

Checkpoint Review Questions and Answers

Checkpoint 3.14

Prompt: Specify the appropriate primitive numeric data type to use for each of the following values:

  • a. 2424 dollars

  • b. 1212 bananas

  • c. 14.514.5 inches

  • d. 8383 cents

  • e. 22 concert tickets

Answers:

  • a. decimal (standard data type for monetary amounts) or int (for whole dollar amounts).

  • b. int (whole count of items).

  • c. double (real number containing a fractional part).

  • d. decimal or int (monetary units/cents).

  • e. int (whole count of items).

Checkpoint 3.15

Prompt: Which of the following variable declarations will cause an error? Why?

  • a. decimal payRate = 24m;

  • b. int playerScore = 1340.5;

  • c. double boxWidth = 205.25;

  • d. string lastName = "Holm";

Answers:

  • Declaration b (int playerScore = 1340.5;) will cause a compilation error.

  • Reason: An int variable cannot accept a double literal containing a fractional part (1340.51340.5) due to assignment compatibility rules and potential loss of data.

Checkpoint 3.16

Prompt: Write a programming statement that will convert the following decimal variable to an int and store the result in an int variable named dollars:

decimal deposit = 976.54m;

Answer:

int dollars = (int)deposit;
Checkpoint 3.17

Prompt: What value will the wholePieces variable contain after the following code executes?

double totalPieces = 6.5;
int wholePieces = (int)totalPieces;

Answer:

  • wholePieces will contain the value 66. The fractional part (.5.5) is truncated during explicit conversion to int.

Checkpoint 3.18

Prompt: Given the following declaration statements, what is the data type of each variable?

  • a. var idNumber1 = "007";

  • b. var idNumber2 = 0.007;

  • c. var idNumber3 = 7;

  • d. var idNumber4 = 7m;

Answers:

  • a. string (initialized with a double-quoted string literal "007").

  • b. double (initialized with a real number literal 0.007).

  • c. int (initialized with an integer literal 7).

  • d. decimal (initialized with a decimal literal 7m).