forked from Confunctionist/finance
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmoney.go
179 lines (149 loc) · 4.24 KB
/
money.go
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package money
/*
The package contains type Money...
type Money struct {
M int64
}
...which usese a fixed-length guard for precision arithmetic: the
int64 variable Guard (and its float64 and int-related variables Guardf
and Guardi.
ROunding is done on float64 to int64 by the Rnd() function truncating
at values less than (.5 + (1 / Guardf)) or greater than -(.5 + (1 / Guardf))
in the case of negative numbers. The Guard adds four decimal places
of protection to rounding.
DP is the decimal precision, which can be changed in the DecimalPrecision()
function. DP hold the places after the decimalplace in teh active money struct field M
The following functions are available
Abs Returns the absolute value of Money
(m *Money) Abs() *Money
Add Adds two Money types
(m *Money) Add(n *Money) *Money
Div Divides one Money type from another
(m *Money) Div(n *Money) *Money
Gett gets value of money truncating after DP (see Value() for no truncation)
(m *Money) Gett() int64
Get gets the float64 value of money (see Value() for int64)
(m *Money) Get() float64
Mul Multiplies two Money types
(m *Money) Mul(n *Money) *Money
Mulf Multiplies a Money with a float to return a money-stored type
(m *Money) Mulf(f float64) *Money
Neg Returns the negative value of Money
(m *Money) Neg() *Money
Pow is the power of Money
(m *Money) Pow(r float64) *Money
Set sets the Money field M
(m *Money) Set(x int64) *Money
Setf sets a float 64 into a Money type for precision calculations
(m *Money) Setf(f float64) *Money
Sign returns the Sign of Money 1 if positive, -1 if negative
(m *Money) Sign() int
String for money type representation in basic monetary unit (DOLLARS CENTS)
(m *Money) String() string
Sub subtracts one Money type from another
(m *Money) Sub(n *Money) *Money
Value returns in int64 the value of Money (also see Gett, See Get() for float64)
(m *Money) Value() int64
*/
import (
"fmt"
"math"
)
type Money struct {
M int64 // value of the integer64 Money
}
func (m *Money) UnmarshalYAML(unmarshal func(interface{}) error) error {
var f float64
unmarshalErr := unmarshal(&f)
if unmarshalErr != nil {
return unmarshalErr
}
m.Setf(f)
return nil
}
// Abs Returns the absolute value of Money
func (m *Money) Abs() *Money {
if m.M < 0 {
m.Neg()
}
return m
}
// Add Adds two Money types
func (m *Money) Add(n *Money) *Money {
r := m.M + n.M
if (r^m.M)&(r^n.M) < 0 {
panic(OVFL)
}
m.M = r
return m
}
// Div Divides one Money type from another
func (m *Money) Div(n *Money) *Money {
f := Guardf * DPf * float64(m.M) / float64(n.M) / Guardf
i := int64(f)
return m.Set(Rnd(i, f-float64(i)))
}
// Gett gets value of money truncating after DP (see Value() for no truncation)
func (m *Money) Gett() int64 {
return m.M / DP
}
// Get gets the float64 value of money (see Value() for int64)
func (m *Money) Get() float64 {
return float64(m.M) / DPf
}
// Mul Multiplies two Money types
func (m *Money) Mul(n *Money) *Money {
return m.Set(m.M * n.M / DP)
}
// Mulf Multiplies a Money with a float to return a money-stored type
func (m *Money) Mulf(f float64) *Money {
i := m.M * int64(f*Guardf*DPf)
r := i / Guard / DP
return m.Set(Rnd(r, float64(i)/Guardf/DPf-float64(r)))
}
// Neg Returns the negative value of Money
func (m *Money) Neg() *Money {
if m.M != 0 {
m.M *= -1
}
return m
}
// Pow is the power of Money
func (m *Money) Pow(r float64) *Money {
return m.Setf(math.Pow(m.Get(), r))
}
// Set sets the Money field M
func (m *Money) Set(x int64) *Money {
m.M = x
return m
}
// Setf sets a float64 into a Money type for precision calculations
func (m *Money) Setf(f float64) *Money {
fDPf := f * DPf
r := int64(f * DPf)
return m.Set(Rnd(r, fDPf-float64(r)))
}
// Sign returns the Sign of Money 1 if positive, -1 if negative
func (m *Money) Sign() int {
if m.M < 0 {
return -1
}
return 1
}
// String for money type representation in basic monetary unit (DOLLARS CENTS)
func (m *Money) String() string {
return fmt.Sprintf("%d.%02d", m.Value()/DP, m.Abs().Value()%DP)
}
// Sub subtracts one Money type from another
func (m *Money) Sub(n *Money) *Money {
r := m.M - n.M
if (r^m.M)&^(r^n.M) < 0 {
panic(OVFL)
}
m.M = r
return m
}
// Value returns in int64 the value of Money (also see Gett(), See Get() for float64)
func (m *Money) Value() int64 {
return m.M
}