diff options
author | creator1creeper1 <creator1creeper1@airmail.cc> | 2021-08-01 13:08:53 +0200 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-08-03 19:12:06 +0430 |
commit | 8f552c9979d92aead2589c8fb3a6d9298faa5603 (patch) | |
tree | 939aa4a17146fd797c14070a874ec49eee2f717e | |
parent | 97d2a5799e78d6d37f55cbd76d0a0d6e2d88aa65 (diff) | |
download | serenity-8f552c9979d92aead2589c8fb3a6d9298faa5603.zip |
Calculator: Use KeypadValue class instead of double
Calculator now uses the KeypadValue class instead of double in
its internal calculations. By not constantly converting to
double back-and-forth, we do not use precision simply by, for
example, negating a number. This fixes #7484.
-rw-r--r-- | Userland/Applications/Calculator/Calculator.cpp | 29 | ||||
-rw-r--r-- | Userland/Applications/Calculator/Calculator.h | 10 | ||||
-rw-r--r-- | Userland/Applications/Calculator/CalculatorWidget.cpp | 11 | ||||
-rw-r--r-- | Userland/Applications/Calculator/CalculatorWidget.h | 3 | ||||
-rw-r--r-- | Userland/Applications/Calculator/Keypad.cpp | 42 | ||||
-rw-r--r-- | Userland/Applications/Calculator/Keypad.h | 5 |
6 files changed, 43 insertions, 57 deletions
diff --git a/Userland/Applications/Calculator/Calculator.cpp b/Userland/Applications/Calculator/Calculator.cpp index a0972927a5..d55fdb5719 100644 --- a/Userland/Applications/Calculator/Calculator.cpp +++ b/Userland/Applications/Calculator/Calculator.cpp @@ -5,6 +5,7 @@ */ #include "Calculator.h" +#include "KeypadValue.h" #include <AK/Assertions.h> #include <AK/Math.h> @@ -16,9 +17,9 @@ Calculator::~Calculator() { } -double Calculator::begin_operation(Operation operation, double argument) +KeypadValue Calculator::begin_operation(Operation operation, KeypadValue argument) { - double res = 0.0; + KeypadValue res = 0; switch (operation) { case Operation::None: @@ -33,30 +34,30 @@ double Calculator::begin_operation(Operation operation, double argument) return argument; case Operation::Sqrt: - if (argument < 0.0) { + if (argument < 0) { m_has_error = true; return argument; } - res = AK::sqrt(argument); + res = KeypadValue { AK::sqrt((double)argument) }; clear_operation(); break; case Operation::Inverse: - if (argument == 0.0) { + if (argument == 0) { m_has_error = true; return argument; } - res = 1 / argument; + res = KeypadValue { 1.0 / (double)argument }; clear_operation(); break; case Operation::Percent: - res = argument * 0.01; + res = argument * KeypadValue { 1, 2 }; // also known as `KeypadValue{0.01}` break; case Operation::ToggleSign: res = -argument; break; case Operation::MemClear: - m_mem = 0.0; + m_mem = 0; res = argument; break; case Operation::MemRecall: @@ -67,7 +68,7 @@ double Calculator::begin_operation(Operation operation, double argument) res = argument; break; case Operation::MemAdd: - m_mem += argument; + m_mem = m_mem + argument; //avoids the need for operator+=() res = m_mem; break; } @@ -75,9 +76,9 @@ double Calculator::begin_operation(Operation operation, double argument) return res; } -double Calculator::finish_operation(double argument) +KeypadValue Calculator::finish_operation(KeypadValue argument) { - double res = 0.0; + KeypadValue res = 0; switch (m_operation_in_progress) { case Operation::None: @@ -93,11 +94,11 @@ double Calculator::finish_operation(double argument) res = m_saved_argument * argument; break; case Operation::Divide: - if (argument == 0.0) { + if (argument == 0) { m_has_error = true; return argument; } - res = m_saved_argument / argument; + res = KeypadValue { (double)m_saved_argument / (double)argument }; break; case Operation::Sqrt: @@ -118,6 +119,6 @@ double Calculator::finish_operation(double argument) void Calculator::clear_operation() { m_operation_in_progress = Operation::None; - m_saved_argument = 0.0; + m_saved_argument = 0; clear_error(); } diff --git a/Userland/Applications/Calculator/Calculator.h b/Userland/Applications/Calculator/Calculator.h index c5a92325a4..1ca9fca5c0 100644 --- a/Userland/Applications/Calculator/Calculator.h +++ b/Userland/Applications/Calculator/Calculator.h @@ -6,6 +6,8 @@ #pragma once +#include "KeypadValue.h" + // This type implements the regular calculator // behavior, such as performing arithmetic // operations and providing a memory cell. @@ -36,8 +38,8 @@ public: MemAdd }; - double begin_operation(Operation, double); - double finish_operation(double); + KeypadValue begin_operation(Operation, KeypadValue); + KeypadValue finish_operation(KeypadValue); bool has_error() const { return m_has_error; } @@ -46,7 +48,7 @@ public: private: Operation m_operation_in_progress { Operation::None }; - double m_saved_argument { 0.0 }; - double m_mem { 0.0 }; + KeypadValue m_saved_argument { (i64)0 }; + KeypadValue m_mem { (i64)0 }; bool m_has_error { false }; }; diff --git a/Userland/Applications/Calculator/CalculatorWidget.cpp b/Userland/Applications/Calculator/CalculatorWidget.cpp index 6ef4b73d50..0343c20886 100644 --- a/Userland/Applications/Calculator/CalculatorWidget.cpp +++ b/Userland/Applications/Calculator/CalculatorWidget.cpp @@ -7,6 +7,7 @@ */ #include "CalculatorWidget.h" +#include "KeypadValue.h" #include <Applications/Calculator/CalculatorGML.h> #include <LibGUI/Button.h> #include <LibGUI/Label.h> @@ -96,8 +97,8 @@ CalculatorWidget::CalculatorWidget() m_equals_button = *find_descendant_of_type_named<GUI::Button>("equal_button"); m_equals_button->on_click = [this](auto) { - double argument = m_keypad.value(); - double res = m_calculator.finish_operation(argument); + KeypadValue argument = m_keypad.value(); + KeypadValue res = m_calculator.finish_operation(argument); m_keypad.set_value(res); update_display(); }; @@ -110,8 +111,8 @@ CalculatorWidget::~CalculatorWidget() void CalculatorWidget::add_operation_button(GUI::Button& button, Calculator::Operation operation) { button.on_click = [this, operation](auto) { - double argument = m_keypad.value(); - double res = m_calculator.begin_operation(operation, argument); + KeypadValue argument = m_keypad.value(); + KeypadValue res = m_calculator.begin_operation(operation, argument); m_keypad.set_value(res); update_display(); }; @@ -130,7 +131,7 @@ String CalculatorWidget::get_entry() return m_entry->text(); } -void CalculatorWidget::set_entry(double value) +void CalculatorWidget::set_entry(KeypadValue value) { m_keypad.set_value(value); update_display(); diff --git a/Userland/Applications/Calculator/CalculatorWidget.h b/Userland/Applications/Calculator/CalculatorWidget.h index ae5e6d399e..b18570a733 100644 --- a/Userland/Applications/Calculator/CalculatorWidget.h +++ b/Userland/Applications/Calculator/CalculatorWidget.h @@ -9,6 +9,7 @@ #include "Calculator.h" #include "Keypad.h" +#include "KeypadValue.h" #include <AK/Vector.h> #include <LibGUI/Widget.h> @@ -17,7 +18,7 @@ class CalculatorWidget final : public GUI::Widget { public: virtual ~CalculatorWidget() override; String get_entry(); - void set_entry(double); + void set_entry(KeypadValue); private: CalculatorWidget(); diff --git a/Userland/Applications/Calculator/Keypad.cpp b/Userland/Applications/Calculator/Keypad.cpp index 243a895f11..9422e467dc 100644 --- a/Userland/Applications/Calculator/Keypad.cpp +++ b/Userland/Applications/Calculator/Keypad.cpp @@ -6,6 +6,8 @@ */ #include "Keypad.h" +#include "KeypadValue.h" +#include <AK/Math.h> #include <AK/StringBuilder.h> Keypad::Keypad() @@ -97,51 +99,29 @@ void Keypad::type_backspace() } } -double Keypad::value() const +KeypadValue Keypad::value() const { - double res = 0.0; - - u64 frac = m_frac_value.value(); - for (int i = 0; i < m_frac_length; i++) { - u8 digit = frac % 10; - res += digit; - res /= 10.0; - frac /= 10; - } - - res += m_int_value.value(); + KeypadValue frac_part = { (i64)m_frac_value.value(), m_frac_length }; + KeypadValue int_part = { (i64)m_int_value.value() }; + KeypadValue res = int_part + frac_part; if (m_negative) res = -res; - return res; } -void Keypad::set_value(double value) +void Keypad::set_value(KeypadValue value) { m_state = State::External; - if (value < 0.0) { + if (value.m_value < 0) { m_negative = true; value = -value; } else m_negative = false; - m_int_value = value; - value -= m_int_value.value(); - - m_frac_value = 0; - m_frac_length = 0; - while (value != 0) { - value *= 10.0; - int digit = value; - m_frac_value *= 10; - m_frac_value += digit; - m_frac_length++; - value -= digit; - - if (m_frac_length > 6) - break; - } + m_int_value = value.m_value / (u64)AK::pow(10.0, (double)value.m_decimal_places); + m_frac_value = value.m_value % (u64)AK::pow(10.0, (double)value.m_decimal_places); + m_frac_length = value.m_decimal_places; } String Keypad::to_string() const diff --git a/Userland/Applications/Calculator/Keypad.h b/Userland/Applications/Calculator/Keypad.h index d090f6ff5c..7d10115942 100644 --- a/Userland/Applications/Calculator/Keypad.h +++ b/Userland/Applications/Calculator/Keypad.h @@ -6,6 +6,7 @@ #pragma once +#include "KeypadValue.h" #include <AK/String.h> // This type implements number typing and @@ -22,8 +23,8 @@ public: void type_decimal_point(); void type_backspace(); - double value() const; - void set_value(double); + KeypadValue value() const; + void set_value(KeypadValue); String to_string() const; |