-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.go
More file actions
215 lines (169 loc) · 4.19 KB
/
main.go
File metadata and controls
215 lines (169 loc) · 4.19 KB
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
package main
import (
"flag"
"fmt"
"log"
"math"
"strconv"
)
func main() {
log.SetFlags(0)
var precision int
flag.IntVar(&precision, "precision", -1, "The number of decimal places to print out")
// Homework Part 1: Global rounding flags
var round bool
flag.BoolVar(&round, "round", false, "Round result to nearest integer")
var floor bool
flag.BoolVar(&floor, "floor", false, "Round result down to nearest integer")
var ceil bool
flag.BoolVar(&ceil, "ceil", false, "Round result up to nearest integer")
flag.Parse()
// Validate mutually exclusive rounding flags
flagCount := 0
if round {
flagCount++
}
if floor {
flagCount++
}
if ceil {
flagCount++
}
if flagCount > 1 {
log.Fatalln("Cannot use multiple rounding flags together")
}
if len(flag.Args()) < 1 {
log.Fatalln("missing subcommand")
}
subcommand := flag.Arg(0)
args := flag.Args()[1:]
// Create rounding config to pass to commands
roundingConfig := RoundingConfig{
Round: round,
Floor: floor,
Ceil: ceil,
}
switch subcommand {
case "add":
addCmd(args, precision, roundingConfig)
case "subtract":
subtractCmd(args, precision, roundingConfig)
case "multiply":
multiplyCmd(args, precision, roundingConfig)
case "divide":
divideCmd(args, precision, roundingConfig)
default:
log.Fatalln("invalid command")
}
}
type RoundingConfig struct {
Round bool
Floor bool
Ceil bool
}
const bitSize = 64
func addCmd(args []string, precision int, rounding RoundingConfig) {
if len(args) != 2 {
log.Fatalln("incorrect arguments for add cmd")
}
num1, err := strconv.ParseFloat(args[0], bitSize)
if err != nil {
log.Fatalln("invalid number:", err)
}
num2, err := strconv.ParseFloat(args[1], bitSize)
if err != nil {
log.Fatalln("invalid number:", err)
}
sum := num1 + num2
printNumber(sum, precision, rounding)
}
func subtractCmd(args []string, precision int, rounding RoundingConfig) {
var isAbsolute bool
flagSet := flag.NewFlagSet("subtract", flag.ExitOnError)
flagSet.BoolVar(
&isAbsolute,
"abs",
false,
"Determines whether or not to print out the absolute value",
)
flagSet.Parse(args)
args = flagSet.Args()
if len(args) != 2 {
log.Fatalln("incorrect arguments for subtract cmd")
}
num1, err := strconv.ParseFloat(args[0], bitSize)
if err != nil {
log.Fatalln("invalid number:", err)
}
num2, err := strconv.ParseFloat(args[1], bitSize)
if err != nil {
log.Fatalln("invalid number:", err)
}
result := num1 - num2
if isAbsolute {
result = math.Abs(result)
}
printNumber(result, precision, rounding)
}
func multiplyCmd(args []string, precision int, rounding RoundingConfig) {
if len(args) != 2 {
log.Fatalln("incorrect arguments for multiply cmd")
}
num1, err := strconv.ParseFloat(args[0], bitSize)
if err != nil {
log.Fatalln("invalid number:", err)
}
num2, err := strconv.ParseFloat(args[1], bitSize)
if err != nil {
log.Fatalln("invalid number:", err)
}
result := num1 * num2
printNumber(result, precision, rounding)
}
func divideCmd(args []string, precision int, rounding RoundingConfig) {
// Homework Part 2: Remainder flag for divide command
var isRemainder bool
flagSet := flag.NewFlagSet("divide", flag.ExitOnError)
flagSet.BoolVar(
&isRemainder,
"remainder",
false,
"Return the integer remainder instead of division result",
)
flagSet.Parse(args)
args = flagSet.Args()
if len(args) != 2 {
log.Fatalln("incorrect arguments for divide cmd")
}
num1, err := strconv.ParseFloat(args[0], bitSize)
if err != nil {
log.Fatalln("invalid number:", err)
}
num2, err := strconv.ParseFloat(args[1], bitSize)
if err != nil {
log.Fatalln("invalid number:", err)
}
// Guard against division by zero
if num2 == 0 {
log.Fatalln("cannot divide by zero")
}
var result float64
if isRemainder {
result = math.Mod(num1, num2)
} else {
result = num1 / num2
}
printNumber(result, precision, rounding)
}
func printNumber(num float64, precision int, rounding RoundingConfig) {
// Apply rounding based on global flags
if rounding.Round {
num = math.Round(num)
} else if rounding.Floor {
num = math.Floor(num)
} else if rounding.Ceil {
num = math.Ceil(num)
}
str := strconv.FormatFloat(num, 'f', precision, bitSize)
fmt.Println(str)
}