summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcreator1creeper1 <creator1creeper1@airmail.cc>2021-08-01 13:08:53 +0200
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2021-08-03 19:12:06 +0430
commit8f552c9979d92aead2589c8fb3a6d9298faa5603 (patch)
tree939aa4a17146fd797c14070a874ec49eee2f717e
parent97d2a5799e78d6d37f55cbd76d0a0d6e2d88aa65 (diff)
downloadserenity-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.cpp29
-rw-r--r--Userland/Applications/Calculator/Calculator.h10
-rw-r--r--Userland/Applications/Calculator/CalculatorWidget.cpp11
-rw-r--r--Userland/Applications/Calculator/CalculatorWidget.h3
-rw-r--r--Userland/Applications/Calculator/Keypad.cpp42
-rw-r--r--Userland/Applications/Calculator/Keypad.h5
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;