-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnumber.h
162 lines (122 loc) · 4.4 KB
/
number.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Defines the Number type for the VM.
//
// The number type is a version of Douglas Crockford's decimal number type,
// but done badly.
#pragma once
#include <cstdint> // intXX_t
#include <cmath> // pow, abs, ...
#include <string> // std::string, std::string::npos
#include <iostream>
namespace fn {
// Types for the exponent and coefficient of a Number.
typedef int8_t Exponent;
typedef int64_t Coefficient;
class Number {
public:
Exponent exponent;
Coefficient coefficient;
Number(Exponent exponent, Coefficient coefficient) {
this->exponent = exponent;
this->coefficient = coefficient;
}
Number(std::string str) {
// To work out what the representation is:
// 1. The component is the number, without the ".",
// 2. The exponent is the distance of the "." from the end of the string
// (or 0 if it's not there).
size_t dotPos = str.find(".");
if (dotPos == std::string::npos) {
this->coefficient = atoi(str.c_str());
this->exponent = 0;
} else {
// Here's an ASCII diagram to explain this one...
//
// -123.456 = -123456 * 10^(-3)
// ^ ^
// 01234 ^
// 3210 ^
// ^---------------------^
size_t dotPosFromEnd = (str.size() - 1) - dotPos;
this->exponent = -1 * dotPosFromEnd;
str.erase(dotPos, 1); // Remove the dot so we can parse the coefficient.
this->coefficient = atoi(str.c_str());
}
}
Number() = default;
std::string toString() {
std::string returnValue = std::to_string(this->coefficient);
if (this->exponent != 0) {
returnValue += " * 10^" + std::to_string(this->exponent);
}
return returnValue;
}
friend Number operator*(Number lhs, Number rhs) {
Number result;
result.exponent = lhs.exponent + rhs.exponent;
result.coefficient = lhs.coefficient * rhs.coefficient;
// TODO: Detect overflow and correct
return result;
}
friend Number operator/(Number lhs, Number rhs) {
Number result;
result.exponent = lhs.exponent - rhs.exponent;
result.coefficient = lhs.coefficient / rhs.coefficient;
// TODO: Divide by 0?
return result;
}
friend Number operator+(Number lhs, Number rhs) {
Number result;
// Get both numbers to the same base.
Exponent exponentDifference = lhs.exponent - rhs.exponent;
Coefficient coefficientMultiplier = (int)pow(10, abs(exponentDifference));
if (exponentDifference < 0) {
rhs.coefficient *= coefficientMultiplier;
result.exponent = lhs.exponent;
} else {
lhs.coefficient *= coefficientMultiplier;
result.exponent = rhs.exponent;
}
result.coefficient = lhs.coefficient + rhs.coefficient;
// TODO: Detect overflow and correct
return result;
}
friend Number operator-(Number lhs, Number rhs) {
Number result;
// Get both numbers to the same base.
Exponent exponentDifference = lhs.exponent - rhs.exponent;
Coefficient coefficientMultiplier = (int)pow(10, abs(exponentDifference));
if (exponentDifference < 0) {
rhs.coefficient *= coefficientMultiplier;
result.exponent = lhs.exponent;
} else {
lhs.coefficient *= coefficientMultiplier;
result.exponent = rhs.exponent;
}
result.coefficient = lhs.coefficient - rhs.coefficient;
// TODO: Detect overflow and correct
return result;
}
friend bool operator==(Number lhs, Number rhs) {
// Get both numbers to the same base.
//
// Here's an example:
// lhs = 200 * 10^3
// rhs = 2 * 10^5
// exponentDifference = 3 - 5 = -2
// so we multiply rhs.coefficient by 100 and drop the coefficient...
// lhs = 200 * 10^5
// rhs = 200 * 10^5
Exponent exponentDifference = lhs.exponent - rhs.exponent;
Coefficient coefficientMultiplier = (int)pow(10, abs(exponentDifference));
if (exponentDifference < 0) {
rhs.coefficient *= coefficientMultiplier;
rhs.exponent = lhs.exponent;
} else {
lhs.coefficient *= coefficientMultiplier;
lhs.exponent = rhs.exponent;
}
return lhs.coefficient == rhs.coefficient
&& lhs.exponent == rhs.exponent;
}
};
}