#include <iostream>
#include <iomanip>
#include <limits>
#include <cmath>
#include <string>
#include <stdexcept>
#include <vector>
/*
Decimal‑fraction → Hexadecimal‑fraction converter
-------------------------------------------------
This program converts ONLY the fractional part (0 ≤ x < 1) of a decimal number
into its hexadecimal fractional representation.
Example:
0.625 (decimal) → 0.A (hex)
0.1 (decimal) → 0.1999999999999... (hex, repeating)
Core idea:
Multiply the fractional part by 16.
The integer part of the result becomes the next hex digit.
Repeat with the new fractional remainder.
Example for 0.625:
0.625 * 16 = 10.0 → digit 'A', remainder 0.0 → stop.
Notes:
- Many decimal fractions have infinite repeating expansions in base 16.
- We cap iterations to avoid infinite loops.
- We detect when the fractional part becomes zero early.
- We use double carefully, but note floating‑point precision limits.
- For production code, consider arbitrary‑precision arithmetic.
Complexity:
O(n) where n = number of digits requested.
Memory usage is minimal (constant).
Performance is excellent for typical use cases.
Security:
Input validation prevents undefined behavior.
Testing edge cases:
- 0.0 → "0.0"
- Very small numbers (e.g., 1e‑12)
- Numbers close to 1 (e.g., 0.999999)
- Repeating fractions (e.g., 0.1)
- Invalid input (negative, >= 1)
Architecture notes:
- Conversion logic isolated in a function.
- Main handles I/O and validation.
- Clear separation of concerns.
*/
// Converts a decimal fraction (0 ≤ x < 1) to a hexadecimal fraction string.
// maxDigits controls how many hex digits to produce.
std::string decimalFractionToHex(double fraction, std::size_t maxDigits = 20) {
if (fraction < 0.0 || fraction >= 1.0) {
throw std::invalid_argument("Fraction must be in [0, 1).");
}
if (fraction == 0.0) {
return "0.0";
}
std::string result = "0.";
for (std::size_t i = 0; i < maxDigits; ++i) {
double scaled = fraction * 16.0;
int digit = static_cast<int>(scaled);
if (digit < 10) {
result.push_back(static_cast<char>('0' + digit));
} else {
result.push_back(static_cast<char>('A' + (digit - 10)));
}
fraction = scaled - digit;
if (std::abs(fraction) < std::numeric_limits<double>::epsilon()) {
break;
}
}
return result;
}
int main() {
std::cout << "Running decimal‑fraction → hexadecimal‑fraction tests:\n\n";
// Test cases including normal, edge, and tricky values
std::vector<double> tests = {
0.0, // trivial zero
0.0625, // exact: 0.1
0.125, // exact: 0.2
0.14, // 0.23D70A3D70A3D8
0.25, // exact: 0.4
0.5, // exact: 0.8
0.625, // exact: 0.A
0.1, // repeating
0.999, // near 1
1e-12, // extremely small
0.999999, // near 1, repeating
0.3333333333 // repeating pattern
//3.14 // Error
};
for (double value : tests) {
try {
std::string hex = decimalFractionToHex(value, 25);
std::cout << "Decimal: " << std::setprecision(12) << value
<< " → Hex: " << hex << "\n";
} catch (const std::exception& ex) {
std::cout << "Decimal: " << value
<< " → Error: " << ex.what() << "\n";
}
}
return 0;
}
/*
run:
Running decimal‑fraction → hexadecimal‑fraction tests:
Decimal: 0 → Hex: 0.0
Decimal: 0.0625 → Hex: 0.1
Decimal: 0.125 → Hex: 0.2
Decimal: 0.14 → Hex: 0.23D70A3D70A3D8
Decimal: 0.25 → Hex: 0.4
Decimal: 0.5 → Hex: 0.8
Decimal: 0.625 → Hex: 0.A
Decimal: 0.1 → Hex: 0.1999999999999A
Decimal: 0.999 → Hex: 0.FFBE76C8B43958
Decimal: 1e-12 → Hex: 0.000000000119799812DEA11
Decimal: 0.999999 → Hex: 0.FFFFEF39085F48
Decimal: 0.3333333333 → Hex: 0.5555555530AED4
*/