diff --git a/Userland/Applications/Calculator/Calculator.cpp b/Userland/Applications/Calculator/Calculator.cpp index 7d065d6029..5af39b6d61 100644 --- a/Userland/Applications/Calculator/Calculator.cpp +++ b/Userland/Applications/Calculator/Calculator.cpp @@ -68,11 +68,14 @@ KeypadValue Calculator::begin_operation(Operation operation, KeypadValue argumen res = argument; break; case Operation::MemAdd: - m_mem = m_mem + argument; //avoids the need for operator+=() + m_mem = m_mem + argument; // avoids the need for operator+=() res = m_mem; break; } + if (should_be_rounded(res)) + round(res); + return res; } @@ -112,6 +115,9 @@ KeypadValue Calculator::finish_operation(KeypadValue argument) VERIFY_NOT_REACHED(); } + if (should_be_rounded(res)) + round(res); + clear_operation(); return res; } @@ -122,3 +128,29 @@ void Calculator::clear_operation() m_saved_argument = 0; clear_error(); } + +bool Calculator::should_be_rounded(KeypadValue value) +{ + // We check if pow(10, value.m_decimal_places) overflow. + // If it does, the value can't be displayed (and provoke a division by zero), see Keypad::set_value() + // For u64, the threshold is 19 + return value.m_decimal_places > rounding_threshold; +} + +void Calculator::round(KeypadValue& value) +{ + while (value.m_decimal_places > rounding_threshold) { + bool const need_increment = value.m_value % 10 > 4; + + value.m_value /= 10; + if (need_increment) + value.m_value++; + + value.m_decimal_places--; + + if (value.m_value == 0) { + value = 0; + return; + } + } +} diff --git a/Userland/Applications/Calculator/Calculator.h b/Userland/Applications/Calculator/Calculator.h index 1ca9fca5c0..91f6c21eff 100644 --- a/Userland/Applications/Calculator/Calculator.h +++ b/Userland/Applications/Calculator/Calculator.h @@ -47,6 +47,22 @@ public: void clear_error() { m_has_error = false; } private: + static bool should_be_rounded(KeypadValue); + static void round(KeypadValue&); + + static constexpr auto rounding_threshold = []() consteval + { + using used_type = u64; + + auto count = 1; + used_type res = 10; + while (!__builtin_mul_overflow(res, (used_type)10, &res)) { + count++; + } + return count; + } + (); + Operation m_operation_in_progress { Operation::None }; KeypadValue m_saved_argument { (i64)0 }; KeypadValue m_mem { (i64)0 }; diff --git a/Userland/Applications/Calculator/KeypadValue.h b/Userland/Applications/Calculator/KeypadValue.h index 3e2ed586fc..3d63e0f27f 100644 --- a/Userland/Applications/Calculator/KeypadValue.h +++ b/Userland/Applications/Calculator/KeypadValue.h @@ -12,6 +12,7 @@ class KeypadValue { friend class Keypad; + friend class Calculator; public: KeypadValue(i64, u8);