Project 2.12 Section 2 ⚡ Embedded Relevance: Core Integer Scaling Precision Loss Multiply-Before-Divide Overflow Percentages

2.12 Integer Ratio Division, Order of Operations & Multiply-Before-Divide Scaling

Executive Summary: Calculating percentage ratios from integer variables. We examine the classic beginner integer division pitfall (e.g. (count / total) * 100 evaluating to 0), enforce the Multiply-Before-Divide rule, and protect against 32-bit overflow using 64-bit intermediate accumulators.

💻 1. Annotated Source Code

#include <iostream>
#include <string>
using namespace std;

int main() {

	string fullName;
	string location;
	int initialScore;

	cout << "Please enter your full name: " << endl;
	getline(cin, fullName);

	cout << "Please enter your city, state/province, and country: " << endl;
	getline(cin, location);

	cout << "Please enter your score (0 to 100): " << endl;
	cin >> initialScore;

	cout << "Hello, " << fullName << endl;
	cout << "We heard you are from " << location << endl;
	cout << "Your original score is " << initialScore
		<< ", but with five points added, your score is "
		<< (initialScore + 5) << endl;

	return 0;
}

📐 2. Architecture & UML Class Model

📐 Fixed-Point Fraction & Floating-Point Model
+ Public - Private # Protected
<<compilation-unit>> PercentageCalculator Math Pipeline
-numerator : double
-denominator : double
+calculatePercentage(num: double, den: double) : double
+calculateBpsFixedPoint(num: int32_t, den: int32_t) : int32_t

📚 3. Core C++ Concepts Deep-Dive

1. The Zero-Result Pitfall

In integer arithmetic, evaluating (part / total) * 100 performs integer division first. When part < total, part / total truncates to 0, resulting in 0 * 100 = 0%!

2. The Multiply-Before-Divide Rule

To preserve precision, always multiply first: (part * 100) / total.

⚡ 4. Embedded Systems & Hardware Reality

1. Preventing Intermediate Overflow

Multiplying part * 100 can overflow 32-bit integer limits if part > 42,949,672. Casting to uint64_t during the multiplication step guarantees 100% overflow immunity.

💡 5. Production-Ready Embedded Refactoring

Safe, high-precision integer percentage calculation:

💡 Production-Ready Refactor
#include <cstdint>

// Calculates percentage (0-100%) with 0 float overhead and 0 overflow risk
constexpr uint32_t calculatePercentage(uint32_t part, uint32_t total) noexcept {
    if (total == 0) return 0;
    // 64-bit promotion prevents 32-bit intermediate multiplication overflow
    return static_cast<uint32_t>((static_cast<uint64_t>(part) * 100UL) / total);
}

📝 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 C++ integer expression '(5 / 10) * 100' evaluate to 0 instead of 50?
A Integer division 5 / 10 truncates to 0 before multiplication by 100 occurs
B The compiler replaces 100 with 0
C Parentheses are illegal in arithmetic expressions
D C++ does not support percentages
Detailed Explanation: Because division occurs first, $5/10 = 0$ in integer arithmetic. Then $0 \times 100 = 0$.
Q2. What is the 'Multiply-Before-Divide' rule in fixed-point and integer embedded math?
A Perform multiplication by the scale factor (e.g. 100) before dividing, preserving precision without fractional truncation
B Always use double precision
C Divide by zero first to check bounds
D Multiply by 2 then shift left
Detailed Explanation: Multiplying before dividing preserves resolution in the upper bits before integer truncation occurs.
Q3. What is the danger of '(part * 1000) / total' when 'part' is a large uint32_t variable?
A 'part * 1000' can overflow the 32-bit integer limit (4,294,967,295), causing silent data corruption
B It triggers a division by zero
C It deletes the total variable
D It causes flash memory wear
Detailed Explanation: If $part \times 1000 > 2^{32}-1$, 32-bit overflow occurs. Casting to uint64_t before multiplication prevents this.
Q4. How do you calculate basis points (0.01% resolution, e.g. 5000 = 50.00%) using integer math?
A (static_cast<uint64_t>(part) * 10000UL) / total
B (part / total) * 10000
C (part * 10) / total
D part % total
Detailed Explanation: Multiplying by 10,000 provides $1/10,000$ ($0.01\%$) resolution with integer arithmetic.