How to Round to the nearest .05 in Java? - java

I got a little project that I had to complete for a job. I am sure you guys have seen this project on here. I am want two things, tip on how to get the correct answer and also a peer review on my solution so far.
public class OrderMethod {
static Map<String, BigDecimal> newOrder;
static final BigDecimal BASICSALES = new BigDecimal(.10);
static final BigDecimal IMPORTSALES = new BigDecimal(.05);
static final BigDecimal BASICANDIMPORTSALES = new BigDecimal(.15);
static final BigDecimal Rounding = new BigDecimal(0.05);
static BigDecimal total = new BigDecimal(0);
public void convertOrders() throws IOException {
ReadFile readfile = new ReadFile();
ArrayList<String> order = readfile.getFile();
newOrder = new LinkedHashMap<String, BigDecimal>();
for(String i : order) {
String[] splitOrder = i.split("at\\ ");
newOrder.put(splitOrder[0], new BigDecimal(splitOrder[1]));
}
}
public void calculate() {
newOrder.forEach((k, v) -> {
if(!((k.contains("chocolate")) || k.contains("book") || k.contains("pill")) && k.contains("import")){
v = v.multiply(BASICANDIMPORTSALES).add(v);
v = v.round(new MathContext(4));
System.out.println("Both " + k + " tax: $" + v);
newOrder.put(k, v);
}
else {
if(!(k.contains("chocolate")|| k.contains("book") || k.contains("pill"))) {
v = v.multiply(BASICSALES).add(v);
v = v.round(new MathContext(4));
System.out.println("Basic " + k + " tax: $" + v);
newOrder.put(k, v);
}
if(k.contains("import")) {
v = v.multiply(IMPORTSALES).add(v);
v = v.round(new MathContext(4));
System.out.println("Import " + k + " tax: $" + v);
newOrder.put(k, v);
}
}
total = total.add(v);
});
}
public void print() {
newOrder.forEach((k, v) -> {
System.out.println(k + ": $" + v);
});
System.out.println("Total: $" + total);
}
public static void main(String[] args) throws IOException {
OrderMethod om = new OrderMethod();
om.convertOrders();
om.calculate();
om.print();
}
}
So what I have done is that I have the program reading a text file containing inputs such as
Input 1:
1 book at 12.49
1 music CD at 14.99
1 chocolate bar at 0.85
Input 2:
1 imported box of chocolates at 10.00
1 imported bottle of perfume at 47.50
Input 3:
1 imported bottle of perfume at 27.99
1 bottle of perfume at 18.99
1 packet of headache pills at 9.75
1 box of imported chocolates at 11.25
These are the list of solutions:
Output:
Output 1:
1 book : 12.49
1 music CD: 16.49
1 chocolate bar: 0.85
Sales Taxes: 1.50
Total: 29.83
Output 2:
1 imported box of chocolates: 10.50
1 imported bottle of perfume: 54.65
Sales Taxes: 7.65
Total: 65.15
Output 3:
1 imported bottle of perfume: 32.19
1 bottle of perfume: 20.89
1 packet of headache pills: 9.75
1 imported box of chocolates: 11.85
Sales Taxes: 6.70
Total: 74.68
I am having a little problem with my calculation. No matter what my answers to Input 2 and 3 seems to be a couple of decimal places off. I get $65.12 for Input 2 and $74.64 for Input 3.
I want help on how to better round up my answers and also what do you think of my code so far.

I don't understand your code but I had to do this on my exam.
I use the operator % like this and it works.
if((number * 100)%10 >= 5)

To round up to 5 cents, you can these :
private static final BigDecimal TWENTY = new BigDecimal(20);
public BigDecimal roundUp5(BigDecimal value)
{
// The final setScale(2) is just to add the ".00" when you display
return value.multiply(TWENTY).setScale(0, BigDecimal.ROUND_CEILING).divide(TWENTY).setScale(2);
}
// You don't need this one as you're using BigDecimal; it's just for completeness!
public double roundUp5(double value)
{
return Math.ceil(value * 20) / 20;
}
Happy to provide my thoughts as a code review.
Firstly, why the separate convertOrders and calculate methods ? Creating the Map in convertOrders, and then iterating across it and re-inserting in calculate is messy and confusing.
Much better would be to have convertOrders call calculate as part of its iteration as each line is read, and therefore create each Map entry correctly as it goes.
You have some repeated expressions that I would refactor into methods for readability and prospect of future business changes, so :
public boolean isBasic(String itemName) {
String name = itemName.toLowerCase();
return !( name.contains("chocolate") || name.contains("book") || name.contains("pill") );
}
public boolean isImport(String itemName) {
String name = itemName.toLowerCase();
return name.contains("import");
}
In your if statements in calculate currently run as :
if (isBasic(k) && isImport(k)) {
// Basic and Import
} else {
if (isBasic(k)) {
}
if (isImport(k)) {
}
}
That flow is a bit confusing, and would be a pain to refactor if in future you needed to also handle non-basic and non-imported items.
There's some common code between all these if blocks, so I would move that out to after the if - which would leave the log statement and the setting of the multiplication factor the only lines remaining in the if blocks.
While we're talking about the multiplication factors, you have those set to values less than 1 (eg 0.15) ... bit then you add v to the result ! It would be much better to have the factors be > 1 and so get rid of the add(v).
Incidentally, it is also preferable to initialise BigDecimal to Strings rather than literal float or double, since those can get rounding errors (eg, 0.15 as a float might actually be 0.1499999999) whereas BigDecimal created from a String is exact.
Assuming you're happy to leave the logging of the final amount to the end, that gets us to something like :
static final BigDecimal BASICSALES = new BigDecimal("1.10");
static final BigDecimal IMPORTSALES = new BigDecimal("1.05");
static final BigDecimal BASICANDIMPORTSALES = new BigDecimal("1.15");
for(String orderLine : order) {
String[] splitOrder = orderLine.split("at\\ ");
String name = splitOrder[0];
BigDecimal value = new BigDecimal(splitOrder[1]));
BigDecimal taxRate;
if(isBasic(name)) {
if (isImport(name)) {
taxRate = BASICANDIMPORTSALES;
System.out.println("Both " + k);
} else {
taxRate = BASICSALES;
System.out.println("Basic " + k);
}
} else {
if (isImport(name)) {
taxRate = IMPORTSALES;
System.out.println("Import " + k);
} else {
taxRate = BigDecimal.ONE;
System.out.println("Neither " + k);
}
}
BigDecimal amountWithTax = amount.multiply(taxRate).round(new MathContext(4));
System.out.println(name + " tax: $" + amountWithTax);
newOrder.put(name, amountWithTax);
}

Related

How do I call these methods? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 1 year ago.
Improve this question
I'm new to Java, and I'm trying to call the private methods I've set up earlier, but with no success. It's a simple program that generates random numbers and display messages. Anyone wants to lend a hand?
Sorry if the code is bad, I've only been learning this for less than month.
import java.util.Random;
import java.util.Scanner;
public class project2 {
private static int rollDie() {
int num_random2 = (int) (Math.random() * 6) + 1;
System.out.println("Die 2: " + num_random2);
return num_random2;
}
private static int rollDie2() {
int num_random = (int) (Math.random() * 6) + 1;
System.out.println("Die 1: " + num_random);
return num_random;
}
private static void printDice(int num_random, int num_random2) {
total = num_random + num_random2;
System.out.println("Total: " + total);
}
int total = num_random + num_random2;
private static void printSpecialMessage(int total) {
String message1 = "Snake Eyes";
String message2 = "Box cars";
if (total = 12) {
System.out.println(message2);
} else if (total = 2) {
System.out.println(message1);
} else {
break;
}
}
public static void main(String[] args) {
System.out.println("Welcome to my app!");
System.out.println();
System.out.println("Dice Roller");
System.out.println();
Scanner sc = new Scanner(System.in);
String choice = "y";
do {
rollDie();
rollDie2();
printDice();
printSpecialMessage();
System.out.print("Roll Again? (y/n): ");
choice = sc.next();
System.out.println();
}
while (choice.equalsIgnoreCase("y"));
}
}
I keep getting these errors:
The method printDice(int, int) in the type project2 is not applicable for the arguments ()
The method printSpecialMessage(int) in the type project2 is not applicable for the arguments ()
at project2.main(project2.java:51)
At this point I'm about to just give up. Hopefully someone can help me out!
Few errors in your code I found.
if (total = 12) should be replaced with if (total == 12).
Make sure you always use two equals in if condition. One = is for assignment and two = for condition check.
printDice() -> The signature is not matching. Pass two values to this function.
total should be declared as static.
printSpecialMessage -> The signature is not matching. Pass one values to this function.
I suggest you start with writing simple code and then gradually go ahead with writing complex codes.
Your code does not compile. The following code does. Compare it with your code.
import java.util.Scanner;
public class Project2 {
private static int rollDie() {
int num_random2 = (int) (Math.random() * 6) + 1;
System.out.println("Die 2: " + num_random2);
return num_random2;
}
private static int rollDie2() {
int num_random = (int) (Math.random() * 6) + 1;
System.out.println("Die 1: " + num_random);
return num_random;
}
private static void printDice(int num_random, int num_random2) {
int total = num_random + num_random2;
total = num_random + num_random2;
System.out.println("Total: " + total);
}
private static void printSpecialMessage(int total) {
String message1 = "Snake Eyes";
String message2 = "Box cars";
if (total == 12) {
System.out.println(message2);
}
else if (total == 2) {
System.out.println(message1);
}
}
public static void main(String[] args) {
System.out.println("Welcome to my app!");
System.out.println();
System.out.println("Dice Roller");
System.out.println();
Scanner sc = new Scanner(System.in);
String choice = "y";
do {
int one = rollDie();
int two = rollDie2();
printDice(one, two);
printSpecialMessage(one + two);
System.out.print("Roll Again? (y/n): ");
choice = sc.next();
System.out.println();
} while (choice.equalsIgnoreCase("y"));
}
}
The things I changed (in no particular order).
Method printSpecialMessage requires an argument. You call that method from method main without an argument. Hence the following [compiler] error.
The method printSpecialMessage(int) in the type Project2 is not applicable for the arguments ()
Similarly for method printDice. That method requires two arguments but you call it with no arguments, which gives the following [compiler] error.
The method printDice(int, int) in the type Project2 is not applicable for the arguments ()
You need to save the value returned from method rollDie in a variable. You also need to save the value returned from method rollDie2 in another variable. Then you call method printDice with those two variables as arguments. In the code above I named the variables one and two.
break is not used in if statements. See method printSpecialMessage.
When comparing integers, use == (double equals sign). Again see method printSpecialMessage.
The following line of code is not inside the body of a method. It belongs in method printDice.
int total = num_random + num_random2;
Here is a sample run of the above code.
Welcome to my app!
Dice Roller
Die 2: 5
Die 1: 3
Total: 8
Roll Again? (y/n): y
Die 2: 6
Die 1: 3
Total: 9
Roll Again? (y/n): n

Java. counting the correct change

I've written a code that supposed to count the change(number of dollars bills, dimes coins, pennies ....). only "pennies" work, but not the way it supposed to be, all the rest lines of code never responds.
public BigDecimal deposit() {
String money = io.readString("Please, deposit money");
BigDecimal deposit = new BigDecimal(money);
return deposit;
}
public void change(String itemId) throws VendingMachinePersistenceException {
Change change = new Change();
Item item = dao.getItem(itemId);\\this line works
BigDecimal change1 = deposit().subtract(item.getPrice());\\this line works
int changeBack = change1.intValue();
io.print("Your change is : ");
change = change.remainder(new BigDecimal("100"));
if (changeBack/100 != 0) {
change.setDollars(changeBack/100);
changeBack = changeBack%100;
io.print(change.getDollars() + " dollars, ");
}
if (changeBack/25 != 0) {
change.setQuarters(changeBack/25);
changeBack = changeBack%25;
io.print(change.getQuarters() + " quarters, ");
}
if (changeBack/10 != 0) {
change.setDimes(changeBack/10);
changeBack = changeBack%10;
io.print(change.getDimes()+ " dimes, ");
}
if (changeBack/5!= 0) {
change.setNickels(changeBack/5);
changeBack = changeBack%5;
io.print(change.getNickels() + " nickels, ");
}
change.setPennies(changeBack);
io.print(change.getPennies()+ " pennies.");
}
It could be the issue with if statements or converting BigDecimal to Int. I'm not sure.
Please, help!
since you're using BigDecimal for money, change1 is probably holding a value like 5.21
converting that to an int will get you just 5 for changeBack, resulting in a nickel for change.
so you probably want to multiply the BigDecimal by 100 before converting it into an int.

Problem with printing the correct item from a 3rd array when comparing two arrays

I am trying to write a shopping list program where the user enters in items on a shopping list with corresponding prices. I have used a String array for the items on the shopping list and a double array for the prices. At the end, the program should print out the most expensive item and the least expensive item.
To do this I made a copy of the price array. Then sorted the original price array using Arrays.sort() so it rearranged in ascending order. After that, I used a for loop to compare the duplicate price array with the sorted original array and when the value in the duplicate is the same as the lowest/highest value in the sorted array I printed the shopping item in the corresponding position from the string array.
This doesn't seem to work exactly as the String being printed doesn't always correspond to the exact position, as it should according to my logic. I cannot figure out where I'm going wrong. I think the problem lies in the getCheapestItem() and getMostExpensiveItem() methods.
Edit:
There might be better ways to do it, like using List or ArrayList, but I need to solve it using Arrays only.
Main class:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static Scanner scanner = new Scanner(System.in);
static int listSize;
static String[] sl;
static double[] price;
static double [] price_duplicate;
public static void main(String[] args) {
Fruit fruit = new Fruit();
shoppingList();
sl = new String[listSize];
price = new double[listSize];
//Loop asking user to enter items and prices
for(int i = 0; i <= listSize - 1; i++)
{
System.out.println("Enter item " + (i+1) + ":");
fruit.setName(scanner.nextLine());
sl[i] = fruit.getName();
System.out.print("Price of " + sl[i] + ":");
fruit.setPrice(scanner.nextDouble());
scanner.nextLine(); //calling nextLine() to get rid of the newline character
price[i] = fruit.getPrice();
}
//Loop printing items and their prices
System.out.println();
System.out.println("-Your shopping list-");
for(int i = 0; i <= listSize - 1; i++)
{
System.out.println(sl[i] + " cost " + price[i]);
}
System.out.println();
//Duplicate the price array
price_duplicate = price;
//Order the array in ascending order so as to be able to easily access lowest and highest values in the array
Arrays.sort(price);
//Identify the cheapest and most expensive items on the shopping list
getCheapestItem();
getMostExpensiveItem();
}
static int shoppingList(){
System.out.print("Enter the number of items in your shopping list:");
listSize = scanner.nextInt();
scanner.nextLine(); //calling nextLine() to get rid of the newline character
return listSize;
}
//Method to match the lowest price in the sorted array to its equivalent value in the duplicate of the original array and print the corresponding string from the sl array, thus identifying the cheapest item on the list
static void getCheapestItem(){
Arrays.sort(price);
for(int i = 0; i < price_duplicate.length; i++){
if(price_duplicate[i] == price[0])
{
System.out.println(sl[i] + " cost(s) " + price[0] + " and is/are the cheapest item(s) on the list.");
}
}
}
//Method to Match the highest price in the sorted array to its equivalent value in the duplicate of the original array and print the corresponding string from the sl array, thus identifying the most expensive item on the list
static void getMostExpensiveItem(){
Arrays.sort(price);
for(int i = price_duplicate.length - 1; i >= 0; i--){
if( price_duplicate[i] == price[price.length - 1])
{
System.out.println(sl[i] + " cost(s) " + price[price.length -1] + " and is/are the most expensive item(s) on the list.");
}
}
}
}
Fruit class:
public class Fruit {
private String name;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
I guess your problem lies in making a copy/duplicate of the price array. You are using price_duplicate=price; which actually not making copy of the price array contents, but just references/points to the same price array object with the duplicate array.
As a result, when you are sorting the original price array, your duplicate array also get sorted. There are several ways to copy an array object to another.
But I would suggest you to use one of your existing code flow, when you are inserting the prices into the original price array, you can also insert them into the duplicate array.
After the price[i]=fruit.getPrice();just add price_duplicate[i]=fruit.getPrice();
And don't forget to initialize the duplicate array as like you initialized the original price array before.
I'm not sure why you are using two arrays, since that makes things more complicated. I would go for a single list static List<Fruit> fruits;.
Then reading the items could be simplified too:
for(int i = 0; i <= listSize - 1; i++)
{
System.out.println("Enter item " + (i+1) + ":");
name = scanner.nextLine();
System.out.print("Price of " + sl[i] + ":");
price = scanner.nextDouble();
scanner.nextLine(); //calling nextLine() to get rid of the newline character
fruits.add(new Fruit(name, price));
}
Of course this means Fruit needs a constructor that requires both name and price. name and price should be defined outside of the loop.
To do the sorting you could use a Comperator<Fruit>.
Comperator<Fruit> compareByPrice = (Fruit f1, Fruit f2) ->
f1.getPrice().compareTo(f2.getPrice());
To sort ascending:
Collections.sort(fruits, compareByPrice);
To sort descending:
Collections.sort(fruits, compareByPrice.reversed());
You don't have to complicate things. You can get cheapest and expensive fruits through fruit objects itself. Look at below example. Create list of Fruit objects. Than do Collections.sort. In Collections.sort you can provide your implementation of Comparator (way to sort any object). In you case sorting has to be done by price. After sorting you can find cheapest fruit in first index and expensive one in last index
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Fruit> fruitList = new ArrayList<>();
fruitList.add(new Fruit("orange", 3.2));
fruitList.add(new Fruit("apple", 9.5));
fruitList.add(new Fruit("banana", 7.4));
fruitList.add(new Fruit("grapes", 1.3));
Collections.sort(fruitList, new Comparator<Fruit>() {
#Override
public int compare(Fruit o1, Fruit o2) {
if (o1.getPrice() < o2.getPrice()) {
return -1;
} else if (o1.getPrice() > o2.getPrice())
{
return 1;
} else {
return 0;
}
}
});
System.out.println("Cheapest fruit " + fruitList.get(0).getName());
System.out.println("Expensive fruit " + fruitList.get(3).getName());
}
}
You use illegal organisation. You should split your code with following parts:
Implement Fruit class, that contain full infromation about single fruit
Implement method, that using console retrieves list of fruits
Define actions to be applied for given list of fruits: get fruits with minimum/maximum prices
Output results.
This is Fruit class implementation. It is immutable.
public final class Fruit {
private final String name;
private final double price;
public Fruit(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
Functions, that receive List<Fruit> and retrieve fruits that reuiqred specific conditions.
Note that price is double value, hence it should be compared correctly, using Double.compare(one, two) == 0 method instead of using one == two.
private static final Function<List<Fruit>, List<Fruit>> GET_CHEAPEST = fruits -> {
final double minPrice = fruits.stream().mapToDouble(Fruit::getPrice).min().orElse(Double.NaN);
return fruits.stream().filter(fruit -> Double.compare(fruit.getPrice(), minPrice) == 0).collect(Collectors.toList());
};
private static final Function<List<Fruit>, List<Fruit>> GET_MOST_EXPENSIVE = fruits -> {
final double maxPrice = fruits.stream().mapToDouble(Fruit::getPrice).max().orElse(Double.NaN);
return fruits.stream().filter(fruit -> Double.compare(fruit.getPrice(), maxPrice) == 0).collect(Collectors.toList());
};
This is method that use Scanner to receive all information about all fruits. Do not forget to close Scanner.
private static List<Fruit> getFruits() {
try (Scanner scan = new Scanner(System.in)) {
System.out.print("Enter the number of items in your shopping list: ");
int total = scan.nextInt();
List<Fruit> fruits = new ArrayList<>(total);
for (int i = 1; i <= total; i++) {
System.out.println("Enter item " + i + ':');
System.out.print("Name: ");
String name = scan.nextLine();
System.out.print("Price: ");
double price = scan.nextDouble();
fruits.add(new Fruit(name, price));
System.out.println();
}
return fruits;
}
}
And finally client code. I believe that now it is pretty simple to realize.
List<Fruit> fruits = getFruits();
List<Fruit> cheapestFruits = GET_CHEAPEST.apply(fruits);
List<Fruit> mostExpensiveFruits = GET_MOST_EXPENSIVE.apply(fruits);
System.out.println("Cheapest fruits:");
cheapestFruits.forEach(fruit -> System.out.format("%s costs %.2f\n", fruit.getName(), fruit.getPrice()));
System.out.println();
System.out.println("Most expensive fruits:");
mostExpensiveFruits.forEach(fruit -> System.out.format("%s costs %.2f\n", fruit.getName(), fruit.getPrice()));
So.. I took an alternative way to process the information. Which I believe is worth you looking at. Although it won't satisfy your problem it will create a working example.
Scanner or anything that involves parsing String to Integer/Double/Short/etc.. has the issue that the String must PERFECTLY equal that value.
In your example you do Scanner.parseDouble(String); The problem is if the user inputs a non decimal value. Your program will crash. On top of that if the decimal is out of precision it will return an invalid or non expected result.
To get around this we use a char array or a value type that far exceeds our needs. In my situation I used a long value. Which has a maximum numeric amount of 9,223,372,036,854,775,807. We don't need anywhere near that amount so it's safe to lock the item to maximum price of 999,999,999.99 and it'll fit millions of times into that value. Then when it comes time to display this value we can convert it into text useable for reading as a price.
I also took on a non array approach to give you insight on another way to find, store, and display the lowest and highest cost items. I also gave you total items and total shopping cost. Hopefully you can use some of these examples for future code.
Another thing to point out his how I converted the String of numbers to a value. There's many way to go about this, but given this situation I choose to loop backwards from the known decimal index or length of string if no decimal was given. We convert the character from 0-9 to a value of 0 to 9. This was done by taking it's char value and taking 48 off it. If the value didn't equal a number between 0 and 9 we skipped it. If it did though we added it to our total value. We started with 100 as our multiplier so 98.76 would give us 9800 price value. Then we add the change which is 99 so gives us a total number of 9876. When we want to convert this into a price. We do 9876 / 100 = 98 and display the 98. Then take 9876 and minus (98 * 100) = 76. So then we display "." and "76". This gives us safe cost displaying and we can support any amount from 0 to 999,999,999.99 safely.
_
import java.util.Scanner;
public class ShoppingList
{
private static long LOWEST_ITEM_COST = Long.MAX_VALUE;
private static long HIGHEST_ITEM_COST = -1;
private static long TOTAL_COST = 0;
private static int TOTAL_ITEMS = 0;
private static String LOWEST_ITEM_NAME;
private static String HIGHEST_ITEM_NAME;
public static void main(String[] args)
{
System.out.print("\nSyntax: FOODNAME PRICE, I.e. Apples $8.50");
while (true)
{
Scanner sc = new Scanner(System.in);
System.out.print("\nEnter a food: ");
String split[] = sc.nextLine().split(" ");
if (split.length > 2)
{
}
if (split.length == 2)
{
String name = split[0];
int length = split[1].length();
int decimal_position = -1;
for (int j = length; --j >= 0; )
{
if (split[1].charAt(j) == '.')
{
decimal_position = j;
break;
}
}
if (decimal_position != -1)
length = decimal_position;
long dollars = 0;
long change = 0;
int place = 100;
for (int c = length; --c >= 0; )
{
int value = (int)split[1].charAt(c) - 48;
if (value < 0 || value > 10)
continue;
if (place == 1000000000) //1 Billion is too large to process stop here!
{
System.out.print("\nPrice Amount exceeds $999,999,999.99 limitation! You entered: " + split[1]);
continue;
}
value *= place;
place *= 10;
dollars += value;
}
place = 10;
if (decimal_position != -1 && (split[1].length() - 3 >= decimal_position))
{
for (int c = decimal_position; c < split[1].length(); ++c)
{
int value = (int)split[1].charAt(c) - 48;
if (value < 0 || value > 10)
continue;
value *= place;
place -= 9;
change += value;
if (place < 0)
break;
}
}
System.out.print("\nItem: " + name + " was added to the shopping cart. Cost: $" + (dollars / 100) + '.' + ((change < 10) ? (change + '0') : (change)));
dollars += change;
if (dollars < LOWEST_ITEM_COST)
{
LOWEST_ITEM_COST = dollars;
LOWEST_ITEM_NAME = name;
}
if (dollars > HIGHEST_ITEM_COST)
{
HIGHEST_ITEM_COST = dollars;
HIGHEST_ITEM_NAME = name;
}
TOTAL_ITEMS++;
TOTAL_COST += dollars;
} else {
if (split.length == 1 && split[0].toLowerCase().contains("done"))
{
break;
}
System.out.print("\nSyntax: FOODNAME PRICE, E.g. IceCream 8.50");
System.out.print("\nTo Finish The Shopping List Simply type: DONE");
continue;
}
}
if (TOTAL_ITEMS == 0)
{
System.out.print("\nNothing Was Added To Your Shopping List Today..");
return;
}
long dollars = HIGHEST_ITEM_COST / 100;
long change = HIGHEST_ITEM_COST - (dollars * 100);
System.out.print("\nHighest Cost Item: " + HIGHEST_ITEM_NAME + " , Costed: " + dollars + '.' + change + ((change < 10) ? '0' : ""));
dollars = LOWEST_ITEM_COST / 100;
change = LOWEST_ITEM_COST - (dollars * 100);
System.out.print("\nLowest Cost Item: " + LOWEST_ITEM_NAME + " , Costed: " + dollars + '.' + change + ((change < 10) ? '0' : ""));
dollars = TOTAL_COST / 100;
change = TOTAL_COST - (dollars * 100);
System.out.print("\nTotal Items Bought: " + TOTAL_ITEMS + " , With a total cost of $" + dollars + '.' + change + ((change < 10) ? '0' : ""));
}
}

Assistance on making a class for a pre-made demo file

I am currently working on an assignment that requires me to create a "bottle class" for a pre-made "bottle demo" file my professor made. This is the description of the assignment:
Write a Bottle class. The class has these 14 methods: read(), set(int), >set(Bottle), get(), and(Bottle), subtract(Bottle), multiply(Bottle), >divide(Bottle), add(int), subtract(int), multiply(int), divide(int), >equals(Bottle), and toString(). The toString() method will be given in class. All >add, subtract, multiply, and divide methods return a Bottle. Your Bottle class >must guarantee bottles always have a positive value and never exceed a maximum >number chosen by you. These numbers are declared as constants of the class. Each >method wit ha parameter must be examined to determine if the upper or lower bound >could be violated. Consider each method carefully and test only the conditions >that could be violated.
And here is the demo code:
public static void main(String[] args) {
int x;
bottle bottle1 = new bottle();
bottle bottle2 = new bottle();
bottle bottle3 = new bottle();
bottle bottle4 = new bottle();
bottle bottle5 = new bottle();
System.out.println("please enter a number for bottle1:");
bottle1.read(); // affected my max and min
System.out.println("Bottle1 is this value " + bottle1 + ".");
System.out.println("Please enter a number for bottle2:");
bottle2.read(); // affected by max and min
bottle3.set(0);
bottle3 = bottle3.add(bottle1);
bottle3 = bottle3.add(bottle2);
bottle3 = bottle3.divide(2);
System.out.println("The 2 bottle average is: " + bottle3 + ".");
System.out.print("Subtracting bottle1 from bottle2 is: " );
bottle3 = bottle2.subtract(bottle1);
System.out.println( bottle3);
bottle3 = bottle2.divide(bottle1);
System.out.println("Dividing bottle2 with bottle1 is: " + bottle3 + ".");
if (bottle1.equals(bottle2))
{
System.out.println("Bottle1 and bottle2 are equal.");
}
else
{
System.out.println("Bottle1 and bottle2 are not equal.");
}
System.out.println("Bottle4 is now given the value of 10 with the set() method.");
bottle4.set(10);
System.out.println("The value of bottle4 is " + bottle4 + ".");
System.out.println("Bottle4 is now multiplied with bottle1. The value is placed in bottle5.");
bottle5 = bottle1.multiply(bottle4);
System.out.println("The value of bottle5 is " + bottle5 + ".");
System.out.println("Enter an integer to add to the value bottle1 has.");
System.out.println("The sum will be put in bottle3.");
Scanner keyboard = new Scanner(System.in);
x = keyboard.nextInt();
bottle3 = bottle1.add(x);
System.out.println("Adding your number " + x +
" to bottle1 gives a new Bottle with " + bottle3 + " in it.");
System.out.print("Adding the number " + bottle2 + " which is the number" +
" in bottle2 to the\nnumber in ");
bottle2 = bottle1.add(bottle2);
System.out.println("bottle1 which is " + bottle1 +" gives " + bottle2 + ".");
}
}
And this is the code I have made so far:
public class bottle {
Scanner scan = new Scanner(System.in);
private int value;
public void Bottle() {
value = 0;
}
public void read() {
value = scan.nextInt();
}
public void set(bottle) {
value = bottle1.value;
}
public void set(int bottle1) {
value = bottle1;
}
public bottle add(bottle) {
value = value + bottle1.value;
}
public bottle subtract(bottle) {
}
public bottle multiply(bottle) {
}
public bottle divide(bottle) {
}
public bottle add(int bottle) {
}
public bottle subtract(int bottle) {
}
public bottle multiply(int bottle) {
}
public bottle divide(int bottle) {
value = value / bottle;
}
public String toString() {
String name = null;
return name;
}
public boolean equals(bottle bottle) {
if (this == bottle) {
return true;
}
else {
return false;
}
}
}
What I need help on is how do I get my methods to work? ( add(int), divide(bottle), divide(int), etc)
And for there to be a max and min for values the user can input, I know that it can be placed at the top of the class code, but how do I make it so that every time the user inputs a number and the math outputs that the max and min will be checked every time to see if any number violates the set rule?
My I know my class code is missing many key components (I think return methods for the math parts) but I am struggling to stay sane trying to figure out what to do. Any help would be greatly appreciated and thanks in advance.
I will also answer any questions that you might have to the best of my ability.
EDIT: I have remade my code after reading the chapter about classes in my textbook and my knowledge is a bit better than before. Here is my new code:
Scanner scan = new Scanner(System.in);
private int value;
private int max = 100;
private int min = 0;
public bottle() {
// sets default value as zero
this.value = 0;
}
public void read() {
value = scan.nextInt();
}
public void set(int value) {
this.value = value;
}
public int add(bottle) {
if (this.value + bottle < this.max && this.value + bottle > this.min)
return this.value + bottle;
else
System.out.println("Please enter another number");
int x = scan.nextInt();
return add(x);
// the few lines above checks to see if the number violates the max and min
}
public int subtract(bottle) {
if (this.value - bottle < this.max && this.value - bottle > this.min)
return this.value - bottle;
else
System.out.println("Please enter another number");
int x = scan.nextInt();
return subtract(x);
}
// though there is this error under the word bottle in the parentheses
public int multiply(bottle) {
if (this.value * bottle < this.max && this.value * bottle > this.min)
return this.value * bottle;
else
System.out.println("Please enter another number");
int x = scan.nextInt();
return multiply(x);
}
public int divide(bottle) {
if (this.value / bottle < this.max && this.value / bottle > this.min)
return this.value / bottle;
else
System.out.println("Please enter another number");
int x = scan.nextInt();
return divide(x);
}
// the String toString method, format as shown by the professor.
public String toString()
{
return this.max + " " + this.min + " " + this.value;
Though I still have 4 errors in my class which is the word bottle inside the parentheses after my add, subtract, multiply, and divide method. Thus the demo file has 8 errors which are all the math methods. I am not sure what to do because "bottle" is an object right? Then how do I add 2 bottles together, or am I taking the wrong approach?
It looks like you're almost on the right track. These will help:
https://www.tutorialspoint.com/java/java_object_classes.htm
https://www.tutorialspoint.com/java/java_methods.htm
Pay attention to what an instance is and also how passing in arguments to methods works along with returning.

Receiving Infinity Value

I'm trying to make a unit conversion program but I keep receiving value as infinity. I'm not sure where I need to fix since it's not giving me errors. I only tested oz to ml to make sure I'm doing it correctly but I'm receiving infinity as the answer.
UnitConverter.java:
public class UnitConverter {
final double oz_TO_ml = 29.5735;
final double gal_TO_g = 3.78541;
final double lb_TO_kg = 0.453592;
final double inc_TO_mm = 25.4;//Inc is inches
final double ft_TO_cm = 30.48;
final double mi_TO_km = 1.60934;
double factor;
public UnitConverter(String unit) {
if (unit.equals("oz")) {
factor = oz_TO_ml;
} else if (unit.equals("gal")) {
factor = gal_TO_g;
} else if (unit.equals("lb")) {
factor = lb_TO_kg;
}
}
public double toOz(double amount) {
return (amount * factor);
}
public double fromOz(double amount) {
return (amount / factor);
}
public double toMl(double amount) {
return (amount * factor);
}
public double fromMl(double amount) {
return (amount / factor);
}
}
Calculator.java:
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Convert from: ");
String fromUnit = in.nextLine();
System.out.print("Convert to: ");
String toUnit = in.nextLine();
UnitConverter from = new UnitConverter(fromUnit);
UnitConverter to = new UnitConverter(toUnit);
System.out.print("Value ");
double val = in.nextDouble();
double oz = from.toOz(val);
double converted = to.fromOz(oz);
System.out.println(val + " " + fromUnit + " = " + converted + " " + toUnit);
}
}
Sample input:
Convert from: oz
Convert to: ml
Value 12
Output:
12.0 oz = Infinity ml
Initialize the factor varible with one. A java with default give 0 to primitive double,
class UnitConvertor {
final double oz_TO_ml = 29.5735;
final double gal_TO_g = 3.78541;
final double lb_TO_kg = 0.453592;
final double inc_TO_mm = 25.4;//Inc is inches
final double ft_TO_cm = 30.48;
final double mi_TO_km = 1.60934;
double factor=1;//initialize with 1
But I am still not sure that what is the check you are using if the user input is 'ml'.
public UnitConverter(String unit)
{
if (unit.equals("oz"))
{
factor = oz_TO_ml;
} else if (unit.equals("gal"))
{
factor = gal_TO_g;
} else if (unit.equals("lb"))
{ factor = lb_TO_kg;
}
}
If you pass "ml" the factor will be zero
Your design currently needs two of these but you really only need one as "oz" has everything it needs to do the conversion.
Ignore the the toUnit in your line input code and just use fromUnit
Edit : I'll show you an alternative way to do things, it just supports one convert to show the rough design. Note the method calls are now static because you will only ever need one instance of them
UnitConverter.java
public class UnitConverter
{
private static final double oz_TO_ml = 29.5735;
public static double convert(String fromType, String toType,double amount) throws IllegalArgumentException
{
if (fromType.equals("oz") && toType.equals("ml"))
{
return (amount * oz_TO_ml);
}
else
{
throw new IllegalArgumentException("The combination of converting " + fromType + " to " + toType + " is not supported");
}
}
}
Calculator.java:
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Convert from: ");
String fromUnit = in.nextLine();
System.out.print("Convert to: ");
String toUnit = in.nextLine();
System.out.print("Value ");
double val = in.nextDouble();
System.out.println(val + " " + fromUnit + " = " + UnitConverter.convert(fromUnit,toUnit,val) + " " + toUnit);
}
}
Your UnitConverter class constructor only knows about 3 units: oz, gal, and lb. If you instantiate it with one of those, it will correctly assign the factor and be able to convert units, as seen below:
public UnitConverter(String unit) {
if (unit.equals("oz")) {
factor = oz_TO_ml;
} else if (unit.equals("gal")) {
factor = gal_TO_g;
} else if (unit.equals("lb")) {
factor = lb_TO_kg;
}
}
However, in your Calculator class, you have this line:
UnitConverter from = new UnitConverter(fromUnit);
UnitConverter to = new UnitConverter(toUnit);
If you run your program with your sample input, from is oz and to is ml. But if you instantiate UnitConverter with the unit ml, what does factor get set to? According to your constructor, it is never set, and so it retains its default value of 0.0.
Later, you call this line:
double converted = to.fromOz(oz);
This runs the fromOz method
public double fromOz(double amount) {
return (amount / factor);
}
Which divides by the factor, which is 0.0. This is the source of your Infinity output.
As the other answer says, you don't need to have two UnitConverter objects to perform this calculation. The factor is correct to convert between ounces and millilitres, so this Calculator code is sufficient.
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Convert from: ");
String fromUnit = in.nextLine();
UnitConverter from = new UnitConverter(fromUnit);
System.out.print("Value ");
double val = in.nextDouble();
double result = from.toMl(val);
System.out.println(val + " " + fromUnit + " = " + result + " ml.");
}
}
If you wanted to keep your current calculator code, you would need to add a condition in your UnitConverter constructor for a scalefactor for ml (1.0). However, I think this approach is flawed because what happens, for example, when you try to convert between oz and inches? The conversion makes no sense but your architecture would not prevent it.

Categories