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
Related
I'm working on a JavaRush Course problem - <Fahrenheit/Celsius Converter>:
Ask user direction of conversion
Ask user a temperature
Convert and print out result temperature
I'm trying to break program on a separate methods to understand how to work with methods and how to pass variables (I'm beginner in programing)
this is my code:
import java.util.Scanner;
public class FahrenheitCelsius {
private static final Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("---< Fahrenheit / Celsius Converter >---");
String direction = getDirection();
int temperature = getTemperature(direction);
getResult(direction, temperature);
sc.close();
}
// let's get direction of conversion from user input
static String getDirection() {
String direction;
do {
System.out.print("Convert from F or C: ");
direction = sc.nextLine();
} while (!direction.equals("F") && !direction.equals("C"));
return direction;
}
// let's get temperature from user
static int getTemperature(String direction) {
int temperature;
System.out.print("temperature in " + direction + ": ");
while (!sc.hasNextInt()) {
System.out.print("temperature in " + direction + ": ");
sc.nextLine();
}
temperature = sc.nextInt();
return temperature;
}
// let's convert Fahrenheit to Celsius
static int fahrenheitToCelsius(int temperatureF) {
return (temperatureF - 32) * 5 / 9;
}
// let's convert Celsius to Fahrenheit
static int celsiusToFahrenheit(int temperatureC) {
return temperatureC * 9 / 5 + 32;
}
// let's get result using direction and temperature we got
static void getResult(String direction, int temperature) {
int result;
if (direction.equals("F")) {
result = fahrenheitToCelsius(temperature);
System.out.println("result temperature: " + result + "C");
} else {
result = celsiusToFahrenheit(temperature);
System.out.println("result temperature: " + result + "F");
}
}
}
But!!!
I'm trying to write getTemperature method using do while loop.
Like this:
static int getTemperature(String direction) {
int temperature;
do {
System.out.print("temperature in " + direction + ": ");
sc.nextInt();
} while (!sc.hasNextInt());
temperature = sc.nextInt();
return temperature;
}
At first I used separate instances of Scanner inside each method. And I got noSuchElementExeption - if user unput characters
Then I got the idea that I dont have to close scanner in getDirection method.
Then I red some advices in Stackoverflow and created separate static final instance of Scanner and passed it into methods
And right now I'm getting - infinite loop if user types characters instead integers
I know that is some weird behaviour with Scanner and this nextLine() thing.
But can't get an idea how to make getTemperature using do while loop without this bug.
Thanks in advance guys.)
Your main() method might contain:
System.out.println("---< Fahrenheit / Celsius Converter >---");
String direction = "";
// Use of the String#matches() method with a small Regular Expression.
// (?i) Ignore Letter Case
// [FC] Only allow the character q, or Q
while (!direction.matches("(?i)[q]")) {
direction = getDirection();
if (!direction.matches("(?i)[q]")) {
int temperature = getTemperature(direction);
printResult(direction, temperature);
}
System.out.println();
}
The getDirection() method might look like:
// let's get direction of conversion from user input
public static String getDirection() {
String direction = "";
while (direction.isEmpty()) {
System.out.println("Enter temperature scale to convert:");
System.out.println(" F) Fahrenheit");
System.out.println(" C) Celsius");
System.out.println(" Q) Quit");
System.out.print("Your choice: --> ");
direction = sc.nextLine();
if (direction.equalsIgnoreCase("q")) {
System.out.println("\nBye-Bye\n");
break;
}
// Use of the String#matches() method with a small Regular Expression.
// (?i) Ignore Letter Case
// [FC] Only allow the characters F, f, C, or c (q is handled ahead of time)
if (!direction.matches("(?i)[FC]")) {
System.err.println("Invalid Temperature Scale Type (" + direction
+ ")! Must be F or C! Try again...\n");
direction = "";
}
}
return direction;
}
The getTemperature() method might look like:
// let's get temperature from user
private static int getTemperature(String direction) {
String temp = "";
// 'Ternary Operators' used here
String directString = (direction.equalsIgnoreCase("f") ? "Fahrenheit" : "Celsius");
String otherDirectString = (direction.equalsIgnoreCase("f") ? "Celsius" : "Fahrenheit");
System.out.println();
System.out.println("Convert a Temperature in " + directString + " to " + otherDirectString + ":");
do {
System.out.print("Enter a temperature in " + directString + ": --> ");
temp = sc.nextLine().trim();
// Since you're working with integer for temperature...
// Use of the String#matches() method with a small Regular Expression.
// ("\\d+") Must be a string representation of an Integer numerical
// value with 1 (or possibly) more digits.
if (!temp.matches("\\d+")) {
System.err.println("Invalid Temperature Supplied (" + temp + ")! Try Again..." );
temp = "";
}
} while (temp.isEmpty());
return Integer.valueOf(temp);
}
The getResult() name is changed to printResult() because that is all it is essentially doing. It's not really getting anything:
// let's get result using direction and temperature we got
static void printResult(String direction, int temperature) {
// 'Ternary Operator' used here
System.out.println("Converted temperature is : "
+ (direction.toUpperCase().equals("F")
? fahrenheitToCelsius(temperature) + "C"
: celsiusToFahrenheit(temperature) + "F"));
}
Other misc. methods remain the same:
// let's convert Fahrenheit to Celsius
public static int fahrenheitToCelsius(int temperatureF) {
return (temperatureF - 32) * 5 / 9;
}
// let's convert Celsius to Fahrenheit
public static int celsiusToFahrenheit(int temperatureC) {
return temperatureC * 9 / 5 + 32;
}
Read the comments in code. You will of course notice that there is use of the String#matches() method for validation along with various small Regular Expressions which are explained in the comments.
You will also notice the use of Ternary Operators to reduce the display of IF/ELSE statements.
I am making a pet veterinary system that has a payment transaction like this.
Whenever I tried to input on 1 jtextfield and calculate it while leave other jtextfield empty, error pops up :
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: empty String
Here is the attached payment transaction menu form
Payment Transaction Menu
How can I get the input and calculate it while ignoring the other text field empty (because for example the customer didn't get the other services, only the consultation service)
Below is my attached code :
double Qty1 = Double.parseDouble(qty_consult.getText());
double Qty2 = Double.parseDouble(qty_dogvac.getText());
double Qty3 = Double.parseDouble(qty_catvac.getText());
double Qty4 = Double.parseDouble(qty_antirabies.getText());
double Qty5 = Double.parseDouble(qty_deworm.getText());
double Qty6 = Double.parseDouble(qty_blood.getText());
double Qty7 = Double.parseDouble(qty_urinalysis.getText());
double Qty8 = Double.parseDouble(qty_skin.getText());
double addup, subTotal, subtotal,tax_ratefee, fee1, fee2, fee3, fee4, fee5, fee6, fee7, fee8;
String consult_fee = String.format("%.2f", price_consultfee);
price_consult.setText(consult_fee);
String vac_fee = String.format("%.2f", price_vacfee);
price_vac.setText(vac_fee);
String vac2_fee = String.format("%.2f", price_vac2fee);
price_vac2.setText(vac2_fee);
String rabies_fee = String.format("%.2f", price_rabiesfee);
price_rabies.setText(rabies_fee);
String deworm_fee = String.format("%.2f", price_dewormfee);
price_deworm.setText(deworm_fee);
String cbc_fee = String.format("%.2f", price_cbcfee);
price_cbc.setText(cbc_fee);
String urine_fee = String.format("%.2f", price_urinefee);
price_urine.setText(urine_fee);
String skin_fee = String.format("%.2f", price_skinfee);
price_skin.setText(skin_fee);
fee1 = Qty1 * price_consultfee;
fee2 = Qty2 * price_vacfee;
fee3 = Qty3 * price_vac2fee;
fee4 = Qty4 * price_rabiesfee;
fee5 = Qty5 * price_dewormfee;
fee6 = Qty6 * price_cbcfee;
fee7 = Qty7 * price_urinefee;
fee8 = Qty8 * price_skinfee;
String sub1 = String.format("%.2f", fee1);
sub_consult.setText(sub1);
String sub2 = String.format("%.2f", fee2);
sub_vac.setText(sub2);
String sub3 = String.format("%.2f", fee3);
sub_vac2.setText(sub3);
String sub4 = String.format("%.2f", fee4);
sub_anti.setText(sub4);
String sub5 = String.format("%.2f", fee5);
sub_deworming.setText(sub5);
String sub6 = String.format("%.2f", fee6);
sub_cbc.setText(sub6);
String sub7 = String.format("%.2f", fee7);
sub_urine.setText(sub7);
String sub8 = String.format("%.2f", fee8);
sub_skin.setText(sub8);
subTotal = fee1 + fee2+ fee3+ fee4 + fee5 + fee6 + fee7 + fee8;
tax_ratefee = (subTotal * taxrate)/100;
//========================Tax=========================//
String subTax = String.format("%.2f", tax_ratefee);
txt_tax.setText(subTax);
//======================SubTotal======================//
String subTotalAll = String.format("%.2f", subTotal);
sub_total.setText(subTotalAll);
//====================OverallTotal=====================//
addup = subTotal + tax_ratefee;
String total = String.format("%.2f", addup);
txt_total.setText(total);
//=====================DateandTime=======================//
Calendar timer = Calendar.getInstance();
timer.getTime();
SimpleDateFormat intime = new SimpleDateFormat ("HH:mm:ss");
txt_time.setText(intime.format(timer.getTime()));
SimpleDateFormat indate = new SimpleDateFormat ("dd-MMM-yyyy");
txt_date.setText(indate.format(timer.getTime()));
I tried doing this :
if (qty_consult.getText().equals("")){
JOptionPane.showMessageDialog(null,"Empty Field/s");
}else {
double Qty1 = Double.parseDouble(qty_consult.getText());
fee1 = Qty1 * price_consultfee;
String consult_fee = String.format("%.2f", price_consultfee);
price_consult.setText(consult_fee);
String sub1 = String.format("%.2f", fee1);
sub_consult.setText(sub1);
subTotal = fee1;
tax_ratefee = (subTotal * taxrate)/100;
//========================Tax=========================//
String subTax = String.format("%.2f", tax_ratefee);
txt_tax.setText(subTax);
//======================SubTotal======================//
String subTotalAll = String.format("%.2f", subTotal);
sub_total.setText(subTotalAll);
//====================OverallTotal=====================//
addup = subTotal + tax_ratefee;
String total = String.format("%.2f", addup);
txt_total.setText(total);
//=====================DateandTime=======================//
Calendar timer = Calendar.getInstance();
timer.getTime();
SimpleDateFormat intime = new SimpleDateFormat ("HH:mm:ss");
txt_time.setText(intime.format(timer.getTime()));
SimpleDateFormat indate = new SimpleDateFormat ("dd-MMM-yyyy");
txt_date.setText(indate.format(timer.getTime()));
and it calculated the input perfectly and after that error of empty string pop-ups again. Am I doing something wrong here?
when working with user input you have to be ready to expect anything, the user always find a way to break your code, so I would recommend you to create a kind of a utility method for accessing and parsing the input. For instance:
private static double getNumberInput(JTextField field, double defaultValue){
String textInput = field.getText();
//Sorry, don't recall if getText can return a null value
//just making sure that we dont have a NullPointerException
//this part can be removed if getText never returns null
texInput = textInput == null? "" : textInput.trim(); //Make sure you trim the value
if("".equals(textInput)){
return defaultValue;
}
try{
return Double.parse(textInput);
}catch(NumberFormatException ex){
//Invalid input
return defaultValue;
}
}
This way you can reuse the method and be sure that when you are trying to get the value inside the field, you always have a value.
double Qty1 = getNumberInput(qty_consult, 0f);
double Qty2 = getNumberInput(qty_dogvac, 0f);
double Qty3 = getNumberInput(qty_catvac, 0f);
This way you'll never have a java.lang.NumberFormatException again.
I have tested the numbers and they hold the correct values but it is printing out the end result completely wrong. E.X: If I put 2/4, it outputs 1
Here is my code:
import java.util.Scanner;
public class FractionConverter {
public static void main(String[] args) {
System.out.println("Welcome To The JEM Fraction Converter!\n");
Scanner sc = new Scanner(System.in);
String num = "0", choice;
System.out.println("Would You Like To Convert From 'Fraction - Decimal'(a) or 'Decimal - Fraction'(b)?");
choice = sc.nextLine();
if (choice.equalsIgnoreCase("a")) {
System.out.println("Please Enter A Fraction (x/y)");
num = sc.nextLine();
String[] parts = num.split("/");
String numerator = parts[0];
String denominator = parts[1];
double result = Double.parseDouble(numerator);
double result2 = Double.parseDouble(numerator);
System.out.println("\n" + numerator + "/" + denominator + " In Decimal Form Is: " + (result/result2));
}
}
}
Appreciate the help!
Replace this line:
double result2 = Double.parseDouble(numerator);
with this:
double result2 = Double.parseDouble(denominator);
double result = Double.parseDouble(numerator);
double result2 = Double.parseDouble(numerator);
... I suppose is a copy/paste problem, isn't it? (both times numerator)
I'm currently working on a GPA calculator for a class of mine. I keep getting an error that has to do with the division I'm trying to do on the GPA calculation and am having trouble with the syntax for sub-strings and how to use them correctly. Below is the code I have so far. If you see anything I can fix that's not to complicated I'm open to all suggestions.
import java.util.Scanner;
public class GPA
{
public static void main(String[] mydata)
{
Scanner sc = new Scanner(System.in);
String choice = "";
String cnum;
String grade;
double points;
double gpa = 0;
int count = 0;
String credit= "", totalCredit = "";
while (!choice.equalsIgnoreCase("Q"))
{
cnum = (mydata[0]);
grade = (mydata[1]);
if (grade.equalsIgnoreCase("A")) {points = 4.0;}
else if (grade.equalsIgnoreCase("B")) {points = 3.0;}
else if (grade.equalsIgnoreCase("C")) {points = 2.0;}
else if (grade.equalsIgnoreCase("D")) {points = 1.0;}
else if (grade.equalsIgnoreCase("F")) {points = 0.0;}
credit = cnum.substring(3,4);
//System.out.println("credits = " + totalCredit);
System.out.println("GPA = " points/Double.parseDouble(credit));
System.out.print("Enter next course number and grade or ‘Q’ to quit: ");
System.out.println();
choice = sc.nextLine();
}
System.out.println("Bye!");
}
}
Not bad but there are a couple syntactical errors with your code:
The println argument needs to be concatenated with a +:
System.out.println("GPA = " + points / Double.parseDouble(credit));
The local variable, points, needs to be initialized since your if-else conditions are not exhaustive (ie: grade has a runtime range of A, B, C, D, or F but grade can technically be assigned to whatever is in mydata[1]). Either add an else condition or assign an initial value to points:
double points = 0.0;
Be sure to include + to concat the strings together :)
System.out.println("GPA = " + (points/Double.parseDouble(credit)));
I believe you want to be concatenating here.
System.out.println("GPA = " + (points/Double.parseDouble(credit)));
Instead of
System.out.println("GPA = " (points/Double.parseDouble(credit)));
And if you want
int theGpa = points/Double.parseDouble(credit));
System.out.println("GPA: " + theGpa);
I was wondering if someone could tell me
1. why, when i input weightNumber with a decimal place, weightConverted doesn't convert it to the whole number, even though I create variable for it?
2. how could i improve this "program" in any way, THANK YOU !!
here is the problem:
code:
import java.util.Scanner;
public class cofee {
public static void main (String []args){
double weightNumber = 0;
String packageType = "";
String serviceType ="";
double totalFee = 0;
double weightConverted = Math.round(weightNumber); // <- this is the problem, should i put it somewhere else?
final double LETTERCOSTP = 12.00;
final double LETTERCOSTS = 10.50;
final double BOXCOSTP = 15.75;
final double BOXCOSTS = 13.75;
final double BOXWEIGHTP = 1.25;
final double BOXWEIGHTS = 1.00;
// input
Scanner input = new Scanner(System.in);
System.out.print("Enter package type (letter/box): ");
packageType = input.nextLine().toLowerCase();
System.out.print("Enter type of service (standard/priority): ");
serviceType = input.nextLine().toLowerCase();
switch(packageType)
{
case "letter":
System.out.print("Enter the weight in ounces: ");
weightNumber = input.nextDouble();
break;
case "box":
System.out.print("Enter the weight in pounds: ");
weightNumber = input.nextDouble();
break;
default:
System.out.print("WRONG PACKAGE TYPE !!!");
}
// letter
if (packageType.equals("letter") && serviceType.equals("priority"))
{
totalFee = LETTERCOSTP;
}
if (packageType.equals("letter") && serviceType.equals("standard"))
{
totalFee = LETTERCOSTS;
}
// box
if (packageType.equals("box") && serviceType.equals("priority"))
{
totalFee = BOXCOSTP + ((weightConverted - 1.0) * BOXWEIGHTP);
}
if (packageType.equals("box") && serviceType.equals("standard"))
{
totalFee = BOXCOSTS + ((weightConverted - 1.0) * BOXWEIGHTS);
}
// display
System.out.println("The fee is € "+ totalFee + " for a package with");
System.out.println("\tType: "+packageType);
System.out.println("\tService: "+serviceType);
System.out.println("\tOunces: "+weightConverted);
}
}
The line double weightConverted = Math.round(weightNumber); will call round() with the value of weightNumber, which is 0, so it rounds 0 to... well... 0, and assigns it to weightConverted.