How would you write a custom class in python using different objects? - java

I'm trying to learn how to code in python, but am having trouble on finding ways to create custom classes online. I wrote a program in java and I am trying to convert it in python. I think I have the custom class down (I'm not sure), and I'm definitely having trouble with the driver.
my custom class (python):
class CostCalculator:
__item = ""
__costOfItem = 0.0
__tax = 0.0
__tip = 0.0
def set_item(self, item):
self.__item = item
def get_name(self):
return self.__item
def set_costOfItem(self, costOfItem):
self.__costOfItem = costOfItem
def get_costOfItem(self):
return self.__costOfItem
def get_tax(self):
__tax = self.__costOfItem * .0875
return self.__tax
def get_tip(self):
__tip = self.__costOfItem * .15
return self.__tip
My python driver attempt
import sys
from CostCalculator import CostCalculator
item = ""
cost = 0.0
totalTip = 0.0
totalTax = 0.0
overallTotal = 0.0
subtotal = 0.0
print("Enter the name of 3 items and their respective costs to get the total value of your meal")
print ("\n Enter the name of your first item: ")
item = sys.stdin.readline()
print("How much is " + item + "?")
cost = sys.stdin.readLine()
My java custom class and driver:
public class TotalCost
{
String item = " ";
double costOfItem = 0;
double tax = 0;
double tip = 0;
public void setItem ( String i )
{
item = i;
}
public String getItem()
{
return item;
}
public void setCostOfItem ( double c )
{
costOfItem = c;
}
public double getCostOfItem ()
{
return costOfItem;
}
public double getTax ()
{
double tax = costOfItem * .0875;
return tax;
}
public double getTip()
{
double tip = costOfItem * .15;
return tip;
}
public String toString()
{
String str;
str = "\nMeal: " + getItem() +
"\nCost of " + getItem() + ": " + getCostOfItem() +
"\nTax of " + getItem() + ": " + getTax() +
"\nTip of " + getItem() + ": " + getTip();
return str;
}
}
import java.util.Scanner;
public class Driver
{
public static void main (String args[])
{
Scanner input = new Scanner (System.in);
String item ;
double cost ;
double totalTip = 0;
double totalTax = 0;
double OverallTotal = 0;
double subtotal;
TotalCost a = new TotalCost ();
TotalCost b = new TotalCost ();
TotalCost c = new TotalCost ();
System.out.println("Enter the name of 3 items and their respective costs to get the total value of your meal");
System.out.println("Enter the name of your first item: ");
item = input.nextLine();
a.setItem ( item );
System.out.println("How much is " + a.getItem() + "?" );
cost = input.nextDouble();
a.setCostOfItem (cost);
input.nextLine();
System.out.println("Enter the name of your second item: ");
item = input.nextLine();
b.setItem (item);
System.out.println("How much is a " + b.getItem() + "?");
cost = input.nextDouble();
b.setCostOfItem (cost);
input.nextLine();
System.out.println("Enter the name of your third item: ");
item = input.nextLine();
c.setItem (item);
System.out.println("How much is a " +c.getItem() + "?" );
cost = input.nextDouble();
c.setCostOfItem(cost);
System.out.println(a + "\n" + b + "\n" + c);
subtotal = a.getCostOfItem() + b.getCostOfItem() + c.getCostOfItem();
totalTip = a.getTip() + b.getTip() + c.getTip();
totalTax = a.getTax() + b.getTax() + c.getTax();
OverallTotal = subtotal + totalTip + totalTax;
System.out.println("\n\tSubtotal: $" + subtotal);
System.out.println("\tTax: $" + totalTax);
System.out.println("\tTip: $" + totalTip);
System.out.println("\tMeal Total: $" + OverallTotal);
}
}

In Python, there is no notion of public vs private, everything is public so you do not need setters or getters.
What you do need is the __init__ function, which is similar to a constructor. You can initialize the member variables here so they are not static and shared among all instances of your class. You can also add default arguments so you many pass in any, all, or none of the arguments to the class upon instantiation.
class CostCalculator:
def __init__(self, item = "", cost = 0.0):
self.item = item
self.cost = cost
def __str__(self):
return 'Meal: {item}\nCost of {item}: {cost}\nTax of {item}: {tax}\nTip of {item}: {tip}'.format(item = self.item, cost = self.cost, tax = self.calc_tax(), tip = self.calc_tip())
def calc_tax(self):
return self.cost * 0.0875
def calc_tip(self):
return self.cost * 0.15
def calc_total(self):
return self.cost + self.calc_tax() + self.calc_tip()
Then you can create an instance of this class. Again note that you can directly access the members without setters or getters, for better or worse ;)
>>> c = CostCalculator('cheese', 1.0)
>>> c.item
'cheese'
>>> c.calc_tip()
0.15
Now you can invoke print on your object
>>> c = CostCalculator('cheese', 1.0)
>>> print(c)
Meal: cheese
Cost of cheese: 1.0
Tax of cheese: 0.085
Tip of cheese: 0.15
Lastly, the way you accept input from a user is generally via input (although messing around with stdin isn't necessarily wrong)
>>> tax = input('how much does this thing cost? ')
how much does this thing cost? 15.0
>>> tax
'15.0'

Another nice feature of Python is the built-in #property decorator,
which helps to replace setters and getters from Java. The #property
decorator allows you to create early versions of a class using property
attributes (i.e., self.tax). If it later becomes necessary to perform
calculations on the attribute or move it to a calculated attribute, the
#property attribute allows this to be done transparently to any
code that depends on the existing implementation. See example, below.
TAX_RATE = 0.0875
TIP_RATE = 0.15
class CostCalculator(object):
def __init__(self, item='', cost=0):
self.item = item
self.cost = cost
#property
def tax(self):
"""Tax amount for item."""
return self.cost * TAX_RATE
#property
def tip(self):
"""Tip amount for item."""
return self.cost * TIP_RATE
if __name__ == '__main__':
item = CostCalculator('Steak Dinner', 21.50)
assert item.tax == 1.8812499999999999
assert item.tip == 3.225

It is like CoryKramer said, python doesn't encourage use of private staff and you don't need setters and getters. But if you still want in, this might help:
class CostCalculator:
__item = ""
__cost_of_item = 0.0
__tax = 0.0
__tip = 0.0
def set_item(self, item):
self.__item = item
def get_name(self):
return self.__item
def set_cost_of_item(self, cost_of_item):
self.__cost_of_item = float(cost_of_item)
def get_cost_of_item(self):
return self.__cost_of_item
def get_tax(self):
self.__tax = self.__cost_of_item * 0.0875
return self.__tax
def get_tip(self):
self.__tip = self.__cost_of_item * 0.15
return self.__tip
item = ""
cost = 0.0
totalTip = 0.0
totalTax = 0.0
overallTotal = 0.0
subtotal = 0.0
print("Enter the name of 3 items and their respective costs to get the total vaalue of your meal")
ls = [CostCalculator(), CostCalculator(), CostCalculator()]
for entry in ls:
print "Enter the name of your item:"
item = raw_input()
entry.set_item(item)
print("How much is " + entry.get_name() + "?")
cost = raw_input()
entry.set_cost_of_item(cost)
subtotal = sum([x.get_cost_of_item() for x in ls])
totalTip = sum([x.get_tip() for x in ls])
totalTax = sum([x.get_tax() for x in ls])

Related

Using multiple arrays as information in a method

I'm struggeling a bit with arrays and user what's inside with loops. I have this question for example (ignore what's inside of the previewOrder method, i was trying stuff out):
public class Ex1_19 {
final static String NAMES[]= {"Spa reine 25 ","Bru plate 50","Bru pét 50",
"Pepsi","Spa orange", "Schweppes Tonic","Schweppes Agr","Ice Tea","Ice Tea Pêche",
"Jus d'orange Looza", "Cécémel", "Red Bull","Petit Expresso","Grand Expresso","Café décaféiné ",
"Lait Russe ","Thé et infusions","Irish Coffee ","French Coffee ","Cappuccino","Cécémel chaud",
"Passione Italiano","Amour Intense", "Rhumba Caliente ","Irish Kisses ","Cuvée Trolls 25",
"Cuvee Trolls 50","Ambrasse-Temps 25","Ambrasse-Temps 50 ","Brasse-Temps Cerises 25",
"Brasse-Temps Cerises 50","La Blanche Ste Waudru 25","Blanche Ste Waudru 50",
"Brasse-Temps citr 25","Brasse-Temps citr 50","Spaghetti Bolo ","Tagl Carbonara",
"Penne poulet baslc ","Tagl American","Tagl saum"};
final static double NETPRICES[]= {2.2, 2.3,3.9,2.2,2.2,2.6,2.6,2.6,2.6,2.6,2.6,4.5,2.2,2.2,2.2,2.5,2.5,7.0,7.0,2.8,2.8,6.2,6.2,6.2,6.2,
2.9,5.5,2.7,5.1,3.1,5.8,2.6,4.9,2.6,4.9,10.8,11.2,12.2,14.5,16.9};
public static void main(String[] args) {
int Order[][]={{3,2},{1,3},{12,4},{37,1},{36,3},{0,0},{0,0},{0,0}, {0,0}};
previewOrder(Order);
}
public static void previewOrder(int order[][]) {
int i = 0;
int j = 0;
while(i < order.length && j < order.length) {
System.out.println(NAMES[i]);
i++;
j++;
}
}
}
My result has to be something like this but with what's inside the "order" array:
Bru pét 50 3.9 2 7,80
Spa reine 25 2.2 3 6,60
Red Bull 4.5 4 18,00
Tagl Carbonara 11.2 1 11,20
Spaghetti Bolo 10.8 3 32,40
In my exercice I have to use a while loop and I have to put the order array in my method parameters. I can't figure out how to make them all communicate.
Sorry if this question has been answered somewhere else but I don't know how to search for it.
EDIT: I know that Orders does not use zero based index, but starts at 1. This is probably because "Order" is supposed to be a user entry. The first number of the array is like a drink number.
I wasn't very clear on the expected output.
Bru pét 50 (NAME[3]) 3.9 (NETPRICE[3]) 2 (Order[][2]) 7.80 NETPRICE[3] * Order[][2] and this for every occurence in Order
The Order array (btw: should be named order or orders) obviously contains references to ordered items and their amount. It's a two dimensional array, like a table with two columns.
Your expected output of "Bru pét 50 3.9 2 7,80", coming from Order[0] {3,2} indicates that the first element (Order[0][0]) is a reference to the items name (from NAMES) and the price (from NETPRICES). The second value of each "row" is the item amount (2) and finally there's the computed total.
For reasons unknown, Orders does not not use zero-based indexed, but starts at 1. So ORDER[0] having value {3,2} actually referes to NAMES[2] and NETPRICES[2]. This needs to be taken into account when picking the right item form NAMES and NETPRICES.
Anyhow: This is what your method could look like. You still need to tweak the output according to your needs.
public static void previewOrder(int order[][]) {
for (int i = 0; i < order.length; i++) {
int index = order[i][0] - 1;
if (index < 0 || index > NAMES.length || index > NETPRICES.length) {
continue;
}
String name = NAMES[order[i][0] - 1];
double price = NETPRICES[order[i][0] - 1];
int amount = order[i][1];
double total = amount * price;
System.out.println(
name + " " + price + " " + amount + " " + total
);
}
}
Try this.
public static void previewOrder(int order[][]) {
Stream.of(order)
.filter(x -> x[0] != 0)
.forEach(x -> {
String name = NAMES[x[0] - 1];
int unit = x[1];
double price = NETPRICES[x[0] - 1];
System.out.printf("%s %.1f %d %.2f%n",
name, price, unit, price * unit);
});
}
output:
Bru p?t 50 3.9 2 7.80
Spa reine 25 2.2 3 6.60
Red Bull 4.5 4 18.00
Tagl Carbonara 11.2 1 11.20
Spaghetti Bolo 10.8 3 32.40
or
public static void previewOrder(int order[][]) {
for (int[] row : order) {
if (row[0] == 0)
continue;
String name = NAMES[row[0] - 1];
int unit = row[1];
double price = NETPRICES[row[0] - 1];
System.out.printf("%s %.1f %d %.2f%n",
name, price, unit, price * unit);
}
}
When I see tightly coupled arrays, I think of creating a class.
public class Product {
String name;
double unitPrice;
public Product () {
name = "*** Unnamed Product ***";
unitPrice = 0.0;
}
public Product (String name, double unitPrice) {
this.name = name;
this.unitPrice = unitPrice;
}
public String getName () { return name; }
public double getPrice () { return unitPrice; }
public String toString () { return name + " # " + unitPrice + " ea.";}
}
Then, you can have one array where you previously had two:
public class Ex1_19 {
static final Product [] productList = {
new Product("Spa reine 25 ", 2.2),
new Product("Bru plate 50", 2.3),
new Product("Bru pét 50", 3.9),
new Product("Pepsi", 2.2),
new Product("Spa orange", 2.2),
new Product("Schweppes Tonic", 2.6),
new Product("Schweppes Agr", 2.6),
new Product("Ice Tea", 2.6)
// and so on
};
}
The preview order method, without formatted output, might look like this:
public static void previewOrder (int[][] order) {
double total = 0.0;
double itemCount = 0;
int lineNum = 0;
for (int i = 0; i < order.length; ++i) {
int row = order[i][0] - 1;
if (row < 0) {
break;
}
int qty = order [i][1];
double amt = productList [row].getPrice () * qty;
System.out.println (++lineNum + " " + productList[row].getName()
+ " " + productList[row].getPrice () + " " + qty
+ " " + amt);
itemCount += qty;
total += amt;
}
System.out.println ("===\nTotal: " + total + " for " + itemCount + " items.");
}

how do i calculate all the total orders together?

import java.util.Scanner;
public class Prac3_Q2_JasmineLimSmith {
Scanner scan;
String set;
int setA = 0, setB = 0, setC = 0, setD = 0;
void createFile() throws Exception {
File file = new File("orders.txt");
scan = new Scanner(file);
}
void readData() {
setA = scan.nextInt();
setB = scan.nextInt();
setC = scan.nextInt();
setD = scan.nextInt();
if (scan.hasNextLine())
scan.nextLine();
}
void calcOrder() {
double order = ((setA * 9.90) + (setB * 10.90) + (setC * 11.90) + (setD * 12.90));
double totalOrder = (order);
System.out.println("Set A " + setA);
System.out.println("Set B " + setB);
System.out.println("Set C " + setC);
System.out.println("Set D " + setD);
System.out.printf("Total price: %.2f", order);
System.out.println();
}
public static void main(String args[]) throws Exception {
Prac3_Q2_JasmineLimSmith cc = new Prac3_Q2_JasmineLimSmith();
cc.createFile();
for (int cnt = 1; cnt <= 10; cnt++) {
cc.readData();
cc.calcOrder();
}
}
}
This is the sample output
Set A 1
Set B 4
Set C 3
Set D 2
Total price: 115.00
Sorry, Im new to java, This is my code so far.
In total there would be 10 outputs like that one.
how would i take all the total prices and calculate it into 1 grand total at the very end?
Any help would be appreciated, Thank you
Welcome to StackOverflow! Are you allowed to change the return types of any methods, or add new parameters/methods? Since this seems like homework, I'll give you a general idea of two possible similar approaches.
One way to do this would be to return the total price from calcOrder (by changing the void return type to double). You can then declare an double sumOfOrders = 0 variable outside of your loop where you call calcOrder and then keep adding the return value of calcOrder to it. At the end of the loop, you will have the sum of all orders which you can print out.
For example:
double calcOrder() { // note that the return type has been changed from 'void' to 'double'
double order = ((setA * 9.90) + (setB * 10.90) + (setC * 11.90) + (setD * 12.90));
// print statements
return order;
}
Then, in your main function, you can use the return value when calling calcOrder():
double sumOfOrders = 0;
for (int cnt = 1; cnt <= 10; cnt++) {
cc.readData();
// The following can alternatively be written as
// sumOfOrders += cc.calcOrder();
sumOfOrders = sumOfOrders + cc.calcOrder();
}
System.out.printf("Sum of all orders: %.2f", sumOfOrders);
If you are not allowed to change the return types of existing methods, you could:
Make order an instance variable (e.g. private double orderPrice;
Set order to the sum of all prices (e.g. this.orderPrice = ((setA * 9.90) + ...);)
Add a getter for the orderPrice variable (e.g. by adding a double getOrderPrice() { return this.orderPrice; } method in your Prac3_Q2_JasmineLimSmith class)
Sum the orders in the same way as above:
double sumOfOrders = 0;
for (int cnt = 1; cnt <= 10; cnt++) {
cc.readData();
cc.calcOrder();
sumOfOrders = sumOfOrders + cc.getOrderPrice();
}
System.out.printf("Sum of all orders: %.2f", sumOfOrders);

Why is my output file printing the payment info backwards?

Why does my text file print the code backward? I need it to print the loan balance decreasing from top to bottom. I didn't include the program that will call the methods, let me know if I should post that as well.
Also, if there are any other discrepancies anyone might see, let me know. Thank you!
package amortizationpack;
import java.io.*;
import java.util.Scanner;
import java.lang.Math;
import java.text.DecimalFormat;
public class Amortization {
double loanAmount;
double interestRate;
double loanBalance;
double term;
double payment;
int loanYears;
Scanner keyboard = new Scanner(System.in);
DecimalFormat number = new DecimalFormat("#,##0.00");
public Amortization(double userLoanAmount, int userLoanYears, double userInterestRate) {
loanAmount = userLoanAmount;
loanYears = userLoanYears;
interestRate = userInterestRate;
calcPayment();
} // constructor
public void calcPayment() {
term = (Math.pow((1 + interestRate / 12), (loanYears * 12)));
payment = (loanAmount * (interestRate / 12) * term) / (term - 1);
} // calcPayment method
public int getNumberOfPayments() {
return loanYears * 12;
} // getNumberofPayments
public void saveReport(String loanFile) throws IOException{
double monthlyInterest;
double principal;
File file = new File("LoanReport.txt");
FileWriter fileWrite = new FileWriter(file);
PrintWriter outputFile = new PrintWriter(fileWrite);
outputFile.println("Monthly payment: " + number.format(payment));
outputFile.println("Month\t\t" + "Interest\t\t" + "Principal\t\t"
+ "Balance");
outputFile.println("--------------------------------------------"
+ "-------------------");
for (int m = 1; m <= getNumberOfPayments(); m++) {
monthlyInterest = interestRate / 12.0 * loanBalance;
if (m != getNumberOfPayments()) {
principal = payment - monthlyInterest;
}
else {
principal = loanBalance;
payment = loanBalance + monthlyInterest;
} // for last payment
loanBalance = loanBalance - principal;
outputFile.print(m + "\t\t"
+ number.format(monthlyInterest) + "\t\t" + number.format(principal) + "\t\t"
+ number.format(loanBalance) + "\n");
} // for loop for writing data to text file
outputFile.close();
System.out.print("File Created");
} // saveReport
} // class
I don't see an answer yet, maybe the way you are printing the values along the getNumberOfPayments() value, but correct me if I'm wrong: you are using the loanBalance variable before assigning it a value.
This answer was in the comments so I don't think I could use it as an official answer, credit goes to user16320675.
Basically, I didn't initialize the loanBalance variable, so it was iterating into the negative numbers from zero, instead of decreasing from the starting balance.

Need a way to associate strings with individual array elements

I am a complete beginner in programming and I'm working on a program for my mother that tracks her employee's monetary intake through a "horse race", with each employee having a horse and the program tracking their input to a UI made to look like a racetrack. After the help from my last inquiry, I've greatly simplified my mess of code but I am now faced with a new problem in that, after sorting the values largest to smallest, I have no way of associating the sorted values with the correct horse. I understand this explanation is confusing so I hope my code will do most of the talking for me here.
I honestly have no idea where to start with this. As I said in my last inquiry, I'm a complete beginner and severely lack the terminology or knowledge to find an answer here.
public class HorseRace {
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String horse1 = "#5 Gitty-Up";
String horse2 = "#7 Lady Simmons";
String horse3 = "#6 Burning Peanutbutter";
String horse4 = "#10 White Lightning";
String horse5 = "#3 Bella";
String horse6 = "#1 Meg The Stallion";
float h1val;
float h2val;
float h3val;
float h4val;
float h5val;
float h6val;
System.out.println("Input amount for " + horse1 + ":");
h1val = sc.nextFloat();
System.out.println("Input amount for " + horse2 + ":");
h2val = sc.nextFloat();
System.out.println("Input amount for " + horse3 + ":");
h3val = sc.nextFloat();
System.out.println("Input amount for " + horse4 + ":");
h4val = sc.nextFloat();
System.out.println("Input amount for " + horse5 + ":");
h5val = sc.nextFloat();
System.out.println("Input amount for " + horse6 + ":");
h6val = sc.nextFloat();
Float[] values = new Float[]{h1val, h2val, h3val, h4val, h5val, h6val};
Arrays.sort(values, Collections.reverseOrder());
//currently displays horses with the wrong number. Need a way to tie the horse name strings to their respective float elements
System.out.println("The current race progress is :");
System.out.println(horse1 + " with $" + values[0]);
System.out.println(horse2 + " with $" + values[1]);
System.out.println(horse3 + " with $" + values[2]);
System.out.println(horse4 + " with $" + values[3]);
System.out.println(horse5 + " with $" + values[4]);
System.out.println(horse6 + " with $" + values[5]);
}
}
my desired result is printing the correct horse with the correct value. For example, if I put that #5 brought in $11 and #7 brought in $14, the program would print that #7 is in the lead with $14 and #5 is in second place with $11.
Currently, the program always prints #5 as being in the lead with the highest value, #7 being in second with the second highest, etc.
I understand this is because I am hard calling the horse1-horse6 values meaning they don't change, but these are acting more as placeholders while I figure out how to associate the right horse with the right value
This is where you should create a Horse class and store the data as instances of Horse.
class Horse {
private String name;
private float value;
public String getName() { return name; }
public float getValue() { return value; }
public void setName(String name) { this.name = name; }
public void setValue(float value) { this.value = value; }
}
And then in your main method:
Horse[] horses = new Horse[6] {
new Horse(), new Horse(), new Horse(), new Horse(), new Horse(), new Horse()
};
horses[0].setName("#5 Gitty-Up");
horses[1].setName("#7 Lady Simmons");
horses[2].setName("#6 Burning Peanutbutter");
// and so on...
// you should use a for loop here instead of writing similar lines over and over again!
for (int i = 0 ; i < 6 ; i++) {
System.out.println("Input amount for " + horses[i].getName() + ":");
horses[i].setValue(sc.nextFloat());
}
Arrays.sort(horses, Comparator.comparingDouble(Horse::getValue).reversed());
System.out.println("The current race progress is :");
for (int i = 0 ; i < 6 ; i++) {
System.out.println(horses[i].getName() + " with $" + horses[i].getValue());
}
By using a class, you are essentially grouping data that belongs together, together. On the line Arrays.sort(horses, Comparator.comparingDouble(Horse::getValue).reversed());, I am sorting the whole array of horses together, by their values.
If the concepts of classes and objects are new to you, that just means it's time to learn about some new concepts. Classes and objects are very important.
Step 1, create a Horse class. It should have two fields, amount and name. It should implement Comparable because you want to sort it. And looking at your desired output, I would override toString().
class Horse implements Comparable<Horse> {
private String name;
private float amount;
public Horse(String name, float amount) {
this.name = name;
this.amount = amount;
}
#Override
public String toString() {
return String.format("%s with $%.2f", name, amount);
}
#Override
public int compareTo(Horse o) {
return Comparator.comparing((Horse h) -> h.amount)
.thenComparing((Horse h) -> h.name).compare(this, o);
}
}
Step 2, create an array of horseNames and iterate that populating an array of Horses (with amounts). Then sort it, and I would prefer Comparator.reverseOrder() to Collection.reverseOrder() when sorting an array.
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
String[] horseNames = { "#5 Gitty-Up", "#7 Lady Simmons",
"#6 Burning Peanutbutter", "#10 White Lightning",
"#3 Bella", "#1 Meg The Stallion" };
Horse[] horses = new Horse[horseNames.length];
for (int i = 0; i < horseNames.length; i++) {
System.out.printf("Input amount for %s:%n", horseNames[i]);
float amt = sc.nextFloat();
horses[i] = new Horse(horseNames[i], amt);
}
Arrays.sort(horses, Comparator.reverseOrder());
System.out.println("The current race progress is :");
for (int i = 0; i < horses.length; i++) {
System.out.println(horses[i]);
}
}

How to utilize a switch statement in this instance?

I'm writing a program that converts units (ex. oz & lb) to new units of measurement (g & kg). I was going to have the user to input the unit they want to convert from and the value of the original unit. I also set constants to convert the selected units. What I'm having an issue with is using a switch statement to determine what conversion I should use (oz ---> g, oz --->, etc).
Here's the code:
System.out.print("Convert from: ");
String origMeasure = input.nextLine();
System.out.print("Convert to: ");
String newMeasure = input.nextLine();
System.out.print("Value: ");
double value = input.nextDouble();
double newValue = 0;
final double OZ_TO_G = 28.3;
final double OZ_TO_KG = 0.028;
final double LB_TO_G = 453.6;
final double LB_TO_KG = 0.045;
final double IN_TO_MM = 25.4;
final double IN_TO_CM = 2.54;
final double IN_TO_M = 0.0254;
final double FT_TO_MM = 304.8;
final double FT_TO_CM = 30.48;
final double FT_TO_M = 0.3048;
final String OZ = " oz";
final String LB = " lb";
final String IN = " in";
final String FT = " ft";
final String G = " g";
final String KG = " kg";
final String MM = " mm";
final String CM = " cm";
final String M = " m";
switch(origMeasure){
case(OZ):
newValue = (value * OZ_TO_G);
break;
}
System.out.println(value + origMeasure + "=" + newValue + newMeasure);
}
}
Concatinate the two strings together and use that as your case statement. So if the user inputs oz for the initial measurement, and then g for the final measurement, you will have switch(initial + final) to yield: ozg.
Have your case statement check for each:
String orig = input.next();
String end = input.next();
switch(orig + end){
case "ozg": //DO MATHEMETICAL FUNCTION HERE TO GET RESULT OF OZ --> G
}
}
You could use a input concatenation + dictionary to do this without a switch statement.
Dictionary<string, float> conversions = new Dictionary<string, float>();
conversion.add("OZ_TO_KG", 28.3);
System.out.print("Convert from: ");
String origMeasure = input.nextLine();
System.out.print("Convert to: ");
String newMeasure = input.nextLine();
System.out.print("Value: ");
double value = input.nextDouble();
string conversion = origMeasure + "_TO_" + newMeasure;
float rate = conversions[conversion];
double newValue = value * rate;
You have to validate if the conversion exists in order to not raise Exceptions.
I suggest you break down your code , in different classes one for each kind of measurement
1. One For Height,Weight etc ..(This would break your problem down)
Each of these classes may have a map , which would hold conversion unit eg,
kg-lb(key) -- > 2.20462(value)
m-cm --> 100 etc
You can put in a Parser which would parse the user input. User input can be in the format like ( 10 kg to lb) . parse the user input and create keys(kg-lb) to be used with map and just multiply the conversion unit
If this utility is something that you intend to extend and maintain in the future, I would suggest that you use enums and separate the conversion into two steps through a common base unit:
public enum UnitType
{
WGT("Weight"),
DST("Distance");
public final String title;
UnitType(String pTitle)
{
title = pTitle;
}
}
public enum Unit
{
//Weight Units: base unit for all is GM
GM(UnitType.WGT, BigDecimal.ONE, "Grams"),
KG(UnitType.WGT, new BigDecimal("1000"), "Kilograms"),
MG(UnitType.WGT, new BigDecimal("0.001"), "Milligrams"),
OZ(UnitType.WGT, new BigDecimal("28.3"), "Ounces"),
LB(UnitType.WGT, (new BigDecimal("16")).multiply(OZ.baseFactor), "Pounds"),
//Distance Units: base unit for all is MTR
MTR(UnitType.DST, BigDecimal.ONE, "Meters"),
MM(UnitType.DST, new BigDecimal("0.001"), "Millimeters"),
CM(UnitType.DST, new BigDecimal("0.01"), "Centimeters"),
KM(UnitType.DST, new BigDecimal("1000"), "Kilometers"),
FT(UnitType.DST, new BigDecimal("0.3048"), "Feet"),
YD(UnitType.DST, (new BigDecimal("3")).multiply(FT.baseFactor), "Yards"),
IN(UnitType.DST, FT.baseFactor.divide(new BigDecimal("12"), 10, BigDecimal.ROUND_HALF_UP), "Inches");
public final UnitType unitType;
public final BigDecimal baseFactor;
public final String title;
Unit(UnitType pUnitType, BigDecimal pBaseFactor, String pTitle)
{
unitType = pUnitType;
baseFactor = pBaseFactor;
title = pTitle;
}
public BigDecimal convert(Unit pTargetUnit, BigDecimal pValue, int pScale)
{
if (pTargetUnit.unitType != unitType)
{
throw new IllegalArgumentException(getErrorMsg(this, pTargetUnit));
}
return pValue.multiply(baseFactor).divide(pTargetUnit.baseFactor, pScale, BigDecimal.ROUND_HALF_UP);
}
private static String getErrorMsg(Unit pSourceUnit, Unit pTargetUnit)
{
StringBuilder sb = new StringBuilder("Cannot convert ");
sb.append(pSourceUnit.unitType.title).append(" (").append(pSourceUnit.title).append(") to ");
sb.append(pTargetUnit.unitType.title).append(" (").append(pTargetUnit.title).append(")");
return sb.toString();
}
}
So usage might look something like this:
public class UnitConverter
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
while (true)
{
System.out.print("Convert from: ");
String sourceUnitName = scanner.next().toUpperCase();
if (sourceUnitName.equals("EXIT"))
{
break;
}
Unit sourceUnit = Unit.valueOf(sourceUnitName);
System.out.println("Source unit: " + sourceUnit.title + System.lineSeparator());
System.out.print("Convert to: ");
String targetUnitName = scanner.next().toUpperCase();
Unit targetUnit = Unit.valueOf(targetUnitName);
System.out.println("Target unit: " + targetUnit.title + System.lineSeparator());
System.out.print("Value: ");
BigDecimal sourceValue = new BigDecimal(scanner.next());
BigDecimal targetValue = sourceUnit.convert(targetUnit, sourceValue, 10);
System.out.println(sourceValue.toString() + " " + sourceUnit.title + " = " + targetValue.toString() + " " + targetUnit.title);
}
}
}
This approach converts in two steps: 1) source unit to common base unit, 2) common base unit to target unit. Without converting through a common base unit, anything other than a very limited number of units and types quickly devolves into an unmaintainable Cartesian product of all-to-all conversion factors

Categories

Resources