Project 2.06 Section 2 ⚡ Embedded Relevance: Core Relational Operators Epsilon Comparison ARM Flags APSR CMP Instruction

2.06 Comparisons (<, <=, ==, !=), Floating-Point Epsilon & ARM Condition Codes (APSR)

Executive Summary: Exploring relational comparison operators. We demonstrate why exact equality comparisons (==) on floating-point numbers fail due to binary representation inaccuracy and how to compare using an epsilon tolerance, and inspect ARM Application Program Status Register (APSR) condition flags (N, Z, C, V).

💻 1. Annotated Source Code

#include <iostream>
using namespace std;

int main() {
	// >   Greater than
	// <   Less than
	// >=  Greater than or equal to
	// <=  Less than or equal to
	// ==  Equal to
	// !=  Not equal to

	cout << boolalpha;

	int a = 15;
	int b = 20;

	cout << (a < b) << endl;

	// equal to
	bool areEqual = (a == b);
	cout << areEqual << endl;

	// challenge 

	int age = 17;
	cout << (age >= 21) << endl;


	return 0;
}

📐 2. Architecture & UML Class Model

📐 Relational Comparison & CPU Condition Flags Model
+ Public - Private # Protected
<<compilation-unit>> RelationalEvaluator APSR Flags (N, Z, C, V)
-threshold : int32_t
-currentValue : int32_t
+isEqual(a: int, b: int) : bool
+isGreater(a: int, b: int) : bool
+isLessOrEqual(a: int, b: int) : bool

📚 3. Core C++ Concepts Deep-Dive

1. Relational Operators

Relational operators (<, >, <=, >=, ==, !=) return boolean values (true / false).

2. The Floating-Point Equality Hazard

Binary floating-point numbers cannot represent decimal fractions like 0.1 exactly ($0.1 + 0.2 \ne 0.3$). Direct equality comparisons (a == b) are dangerous. Use epsilon tolerance checks: std::abs(a - b) < EPSILON.

⚡ 4. Embedded Systems & Hardware Reality

1. ARM Cortex-M Condition Flags (APSR)

The CMP instruction subtracts two operands and sets flags in the Application Program Status Register (APSR):

  • Z (Zero): Set if result is zero (equality).
  • N (Negative): Set if result is negative.
  • C (Carry): Set on unsigned overflow/no-borrow.
  • V (oVerflow): Set on signed arithmetic overflow.

💡 5. Production-Ready Embedded Refactoring

Robust floating-point and fixed-point comparison helper:

💡 Production-Ready Refactor
#include <cmath>

constexpr float EPSILON = 0.0001f;

constexpr bool areFloatsEqual(float a, float b) noexcept {
    float diff = a - b;
    return (diff < 0.0f ? -diff : diff) < EPSILON;
}

📝 Knowledge Verification Quiz

Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.

Q1. Why does the expression '0.1f + 0.2f == 0.3f' evaluate to false in C++?
A Binary IEEE 754 floating-point cannot represent 0.1 and 0.2 exactly, resulting in small rounding discrepancies
B C++ does not allow adding two float literals
C Floating point equality is disabled at -O2
D 0.3f is promoted to double automatically
Detailed Explanation: Binary floating-point represents numbers as fractions with powers of 2 in the denominator; decimal fractions like 0.1 produce repeating binary fractions that suffer rounding truncation.
Q2. How should two floating-point sensor values be compared for equality in safety-critical firmware?
A Check if the absolute difference is less than an acceptable epsilon threshold: std::abs(a - b) < EPSILON
B Use the '===' operator
C Cast both floats to void*
D Multiply both by zero
Detailed Explanation: Comparing against an epsilon tolerance accounts for floating-point representation and calculation rounding errors.
Q3. Which ARM APSR status flag is set to 1 when a comparison (CMP R0, R1) detects two equal values?
A Z (Zero) flag
B N (Negative) flag
C V (Overflow) flag
D C (Carry) flag
Detailed Explanation: CMP R0, R1 computes $R0 - R1$. If they are equal, the result is zero, setting the Z (Zero) condition flag to 1.
Q4. What is the return type of relational expressions (e.g. 5 > 3) in C++?
A bool (evaluating to true or false)
B int (1 or 0)
C uint8_t
D size_t
Detailed Explanation: Relational operators in C++ return boolean type (bool).