Background info on factoring and prime factorization.
I've remade this program from my first attempt, and I'm sure it can still be improved. My questions:
- These calculations should only be done with positive integers. Would something like
templates help keep this type-safe? What about throwing an exception? - Is this an effective way to use the
typedefs? Only the classes need them, so it seems better to qualify them with each class rather than anamespace. - Can both
calculate()s be better optimized, considering they perform numerous divisions? - I'm not quite liking the call to
calculate()in bothdisplay()s, even though there are no data member changes. Is this still okay? It doesn't quite make sense to perform the calculations in the constructor, andcalculate()should still beprivate.
Factors.h
#ifndef FACTORS_H #define FACTORS_H #include <cstdint> #include <map> class Factors { private: typedef std::map<std::uint64_t, std::uint64_t> FactorsList; std::uint64_t integer; FactorsList calculate() const; public: Factors(std::uint64_t); void display() const; }; #endif Factors.cpp
#include "Factors.h" #include <cmath> #include <iostream> Factors::Factors(std::uint64_t i) : integer(i) {} Factors::FactorsList Factors::calculate() const { float sqrtInt = std::sqrt(static_cast<float>(integer)); FactorsList factors; for (std::uint64_t i = 1; i <= sqrtInt; ++i) { if (integer % i == 0) { factors[i] = integer / i; } } return factors; } void Factors::display() const { FactorsList factors = calculate(); for (auto iter = factors.cbegin(); iter != factors.cend(); ++iter) { std::cout << iter->first << " x " << iter->second << "\n"; } } Primes.h
#ifndef PRIMES_H #define PRIMES_H #include <cstdint> #include <map> class Primes { private: typedef std::map<std::uint64_t, std::uint64_t> PrimesList; std::uint64_t integer; PrimesList calculate() const; public: Primes(std::uint64_t); void display() const; }; #endif Primes.cpp
#include "Primes.h" #include <iostream> Primes::Primes(std::uint64_t i) : integer(i) {} Primes::PrimesList Primes::calculate() const { std::uint64_t intCopy = integer; std::uint64_t divisor = 2; PrimesList primes; while (intCopy % divisor == 0) { intCopy /= divisor; primes[divisor]++; } for (divisor = 3; intCopy > 1; divisor += 2) { while (intCopy % divisor == 0) { intCopy /= divisor; primes[divisor]++; } } return primes; } void Primes::display() const { PrimesList primes = calculate(); for (auto iter = primes.cbegin(); iter != primes.cend(); ++iter) { if (iter != primes.cbegin()) std::cout << " x "; std::cout << iter->first; if (iter->second > 1) std::cout << '^' << iter->second; } }
Primes::calculateby checking 2 independently, and then only checking odd numbers. (Once you've factored out all the 2s,intCopywon't be divisible by any even number.) \$\endgroup\$