I'm writing a program that will calculate the BMI of a person. Here's the assignment that I was given:
"Body Mass Index (BMI) is a measure of health on weight. It can be calculated by taking your weight in kilograms and dividing by the square of your height in meters. Write a program that prompts the user to enter a weight W in pounds and height H in inches and displays the BMI. Note that one pound is 0.45359237 kilograms and one inch is 0.0254 meters."
Input: (Line 1) Real number within 50 to 200
(Line 2) Real number within 10 to 100
Output: BMI value (Floating point should only be printed until the second decimal point)
The problem is that whenever I use "System.out.printf("%.2f\n", BMI)", the output is rounded up rather than cutting off the rest of the decimal point. Here's my code:
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
double weight = input.nextDouble();
double height = input.nextDouble();
double weightKG;
double heightM;
double heightMSquare;
double BMI;
final double kilogram = 0.45359237;
final double meter = 0.0254;
while ((weight > 200) || (weight < 50)) // Error catching code.
{
weight = input.nextDouble();
}
while ((height > 100) || (height < 10))
{
height = input.nextDouble();
}
weightKG = weight * kilogram; // Convert pounds and inches to
kilograms and meters.
heightM = height * meter;
heightMSquare = Math.pow(heightM, 2); // Compute square of height in
meters.
BMI = weightKG / heightMSquare; // Calculate BMI by dividing weight
by height.
System.out.printf("%.2f\n", BMI);
}
}
Here is a method I wrote that solves this with regexes and string manipulation.
private static String format2Dp(double x) {
String d = Double.toString(x);
Matcher m = Pattern.compile("\\.(\\d+)").matcher(d);
if (!m.find()) {
return d;
}
String decimalPart = m.group(1);
if (decimalPart.length() == 1) {
return d.replaceAll("\\.(\\d+)", "." + decimalPart + "0");
}
return d.replaceAll("\\.(\\d+)", "." + decimalPart.substring(0, 2));
}
What I did was turning the double to a string, extract the decimal part out of it and substringing the decimal part. If the decimal part is only 1 character long, add a zero to the end.
This method works with numbers expressed in scientific notation as well.
Related
New error:
import java.util.Scanner;
public class BMICalculator {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Length in meters: ");
double length = input.nextDouble();
System.out.print("Weight in kilos: ");
double weight = input.nextDouble();
double bmi = weight / length * length;
System.out.printf("BMI");
input.close();
}
}
You're considering variables meter and bmi to be of type double. However, the expression on the right hand side of assignment is divide operation among int which will cause precision loss.
You'll need to cast one of the operands on right hand side to double to preserve precision.
double meter = (double) centimeter / 100;
double bmi = (double) weight / (meter * meter);
In your System.out.printf, you're using the non-existing length variable. As I understand, there should be meter variable there.
I've also fixed a typo in first System.out.print in Length word.
The fixed class looks like this (UPDATE: also fixed the integer division, which was the actual question's target):
import java.util.Scanner;
public class BMICalculator {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Length in centimeter: ");
int centimeter = input.nextInt();
double meter = ((double) centimeter) / 100; // fixed integer division by casting to double
System.out.print("Weight in whole kilo: ");
int weight = input.nextInt();
double bmi = ((double) weight) / (meter * meter); // fixed integer division by casting to double
System.out.printf("BMI for someone who is %.2f meter long, and weight %d kilo is %.1f", meter, weight, bmi);
input.close();
}
}
Here is my code. For some reason my BMI is not calculated correctly.
When I check the output on a calculator for this : (10/((10/100)^2))) I get 1000, but in my program, I get 5. I'm not sure what I am doing wrong. Here is my code:
import javax.swing.*;
public class BMI {
public static void main(String args[]) {
int height;
int weight;
String getweight;
getweight = JOptionPane.showInputDialog(null, "Please enter your weight in Kilograms");
String getheight;
getheight = JOptionPane.showInputDialog(null, "Please enter your height in Centimeters");
weight = Integer.parseInt(getweight);
height = Integer.parseInt(getheight);
double bmi;
bmi = (weight/((height/100)^2));
JOptionPane.showMessageDialog(null, "Your BMI is: " + bmi);
}
}
^ in java does not mean to raise to a power. It means XOR.
You can use java's Math.pow()
And you might want to consider using double instead of int—that is:
double height;
double weight;
Note that 199/100 evaluates to 1.
we can use
Math.pow(2, 4);
this mean 2 to the power 4 (2^4)
answer = 16
^ is not the operator you want. You are looking for the pow method of java.lang.Math.
You can use Math.pow(value, power).
Example:
Math.pow(23, 5); // 23 to the fifth power
Your calculation is likely the culprit. Try using:
bmi = weight / Math.pow(height / 100.0, 2.0);
Because both height and 100 are integers, you were likely getting the wrong answer when dividing. However, 100.0 is a double. I suggest you make weight a double as well. Also, the ^ operator is not for powers. Use the Math.pow() method instead.
Too late for the OP of course, but still...
Rearranging the expression as:
int bmi = (10000 * weight) / (height * height)
Eliminates all the floating point, and converts a division by a constant to a multiplication, which should execute faster. Integer precision is probably adequate for this application, but if it is not then:
double bmi = (10000.0 * weight) / (height * height)
would still be an improvement.
You should use below method-
Math.pow(double a, double b)
From (https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#pow-double-double-)
Returns the value of the first argument raised to the power of the second argument.
int weight=10;
int height=10;
double bmi;
bmi = weight / Math.pow(height / 100.0, 2.0);
System.out.println("bmi"+(bmi));
double result = bmi * 100;
result = Math.round(result);
result = result / 100;
System.out.println("result"+result);
1) We usually do not use int data types to height, weight, distance,
temperature etc.(variables which can have decimal points)
Therefore height, weight should be double or float.
but double is more accurate than float when you have more decimal points
2) And instead of ^, you can change that calculation as below using Math.pow()
bmi = (weight/(Math.pow(height/100, 2)));
3) Math.pow() method has below definition
Math.pow(double var_1, double var_2);
Example:
i) Math.pow(8, 2) is produced 64 (8 to the power 2)
ii) Math.pow(8.2, 2.1) is produced 82.986813689753 (8.2 to the power 2.1)
I did the benchmarking with Math.pow(x,2) and x*x,
the result is that Math.pow() is easily forty times slower than manually multiplying it by itself, so i don't recommend it for anything where a little bit of performance is required.
Here's the results:
proof_of_work: 19.284756867003345
time for Math.pow(x,2) in ns: 35143
proof_of_work: 19.284756867003345
time for x*x in ns: 884
manual calculation is 39 times faster
and here's the test-code
double r1 = 4.391441320;
long multiply_d1 = System.nanoTime();
double multiply_dr = Math.pow(r1,2);
long multiply_d2 = System.nanoTime();
System.out.println(("proof_of_work: ") + (multiply_dr));
System.out.println(("time for Math.pow(x,2) in ns: ") + (multiply_d2 - multiply_d1));
long multiply_t1 = System.nanoTime();
double multiply_tr = r1*r1;
long multiply_t2 = System.nanoTime();
System.out.println(("proof_of_work: ") + (multiply_tr));
System.out.println(("time for x*x in ns: ") + (multiply_t2 - multiply_t1));
System.out.println(("manual calculation is ") + ((multiply_d2 - multiply_d1) / (multiply_t2 - multiply_t1)) + (" times faster"));
Most efficient solution is
public Float fastPow(Float number, Integer power) {
if (power == 0) {
return 1.0f;
} else if (power % 2 == 1) {
return fastPow(number, power - 1) * number;
} else {
return fastPow(number * number, power / 2);
}
}
Let A is our number and N our power. Then A^2^N = (A^2)^N. And A^N = (A^2)^N/2. The function above reflects this relationship.
I am getting a NaN error when I compile this, i can't figure out what I am doing wrong? I tried moving the variables around to see if I could get them working but nothing. Notice the variable I put of type double i used for bmi after inches = keyboard.nextInt(); I think its a divide by zero error but i dont know what i am dividing by zero.
import java.util.Scanner;
public class BodyMassIndex {
public static void main(String[] args) {
// TODO Auto-generated method stub
int pounds =0;
int feet = 0;
int inches = 0;
double heightMeters = ((feet * 12) + inches) * .0254;
double mass = pounds / 2.2;
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter your weight in pounds");
pounds = keyboard.nextInt();
System.out.println("Enter how many feet you are");
feet = keyboard.nextInt();
System.out.println("Enter how many inches after feet");
inches = keyboard.nextInt();
double bmi = mass / (heightMeters * heightMeters);
System.out.println(mass);
System.out.println(bmi);
if(bmi < 18.5){
System.out.println("Underweight");
}
else if ((bmi >= 18.5) && (bmi < 25)){
System.out.println("Normal weight");
}
else if ((bmi >= 25) && (bmi < 30))
System.out.println("Above weight");
else
System.out.println("Obese");
}
}
It's important to understand the dynamic nature of your variables, such that when you type
double heightMeters = ((feet * 12) + inches) * .0254;
This assignment is immediately evaluated using the current values of feet and inches (which are 0 at that moment), before any of the keyboard entry is performed. To perform these calculations with the values entered by the keyboard, these calculations need to be performed and their results assigned to their corresponding variables after the keyboard entry is done, when the current values of pounds, feet and inches are what you just entered. Because heightMeters is still zero from its initialization and hasn't been changed since, you're getting a divide by zero.
You're getting the exception because the value of heightMeters is 0 here:
double bmi = mass / (heightMeters * heightMeters);
The only time that heightMeters is calculated, the result of it is 0:
double heightMeters = ((feet * 12) + inches) * .0254;
It looks like you want to use this calculation, so I'd split it into a separate function:
public static double getHeightInMeters(int feet, int inches)
{
return 0.0254 * ((feet * 12) + inches);
}
Then you can call it later:
double heightMeters = this.getHeightInMeters(feet, inches);
double bmi = mass / (heightMeters * heightMeters);
I seem to have gotten my self lost in my own programing. directly below is what the outcome is suppose to look like. I am desperately needing help as am new to java coding and becoming quickly aware I am not very good at. Please fill free to correct the code as needed. I learn better when i know what the mistake is. Thank you for any help you can provide.
This program implements a Health Assistance Calculator
Given a weight, height, and age, it will compute:
BMI - body mass index
Calories needed per day to maintain weight
Please enter your weight in pounds: 150
Please enter your height in inches: 66
Please enter your age in years: 30
Your BMI is 24.3
A BMI in the range of 18.5 to 24.9 is considered normal
To maintain your current weight:
Men need 2249 calories per day
Women need 2018 calories per day
Method 1: A method to display an explanation of what the program will do to the user.
o This method will not have any parameters or return values.
Method 2: A method to compute a person’s BMI. This method must:
o Have 2 parameters: weight in kgs and height in meters
o Use the pow method from in the java.Math class to square the height
o Return a double value: the calculated BMI
Methods 3 & 4: Two methods to compute the caloric requirements, one for a man and one for a
woman. Each of these methods must:
o Have 3 parameters: weight in kgs, height in meters, and age
o Convert the height to centimeters.
o Compute the caloric requirements.
o Use one of the rounding methods in the java.Math class to round the answer to a whole
number before returning it. Note that you may need to use casting to convert the value
returned from the java.Math method to an integer.
o Return an integer value: the daily calories required to maintain current weight
Method 5: A method to display the results, with no return value. This method must:
o Have 3 parameters: a person’s BMI, men’s calories, and women’s calories
o Display a description and the BMI, rounded to one decimal place using the printf method
from the System.out class
o Display the daily calories required to maintain current weight for men
o Display the daily calories required to maintain current weight for women
enter code here
package healthy;
import java.util.*;
import java.lang.Math;
public class Healthy {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
printIntroduction();
double kg = .453592;
double feet = .3048;
double bmi = BMIinput(console);
double age = InputAge(console);
double Wt = InputWeight(console);
double Ht = InputHeight(console);
double MetricConvert = Metric();
String status = getStatus(bmi);
String converted = getConverted(MetricConvert);
}
//Prints program description
public static void printIntroduction(){
System.out.println("This program Implements a Health Assistance Calculator")
System.out.println("Given a Weight, Height, and age, it will compute: ");
System.out.println(" BMI - body mass index");
System.out.println(" Calories needed per day to maintain weight");
System.out.println("");
}
//Prompts user to input weight, height and age.
public static double BMIinput(Scanner console){
System.out.println("Please enter your weight in pounds: ");
double Inputweight = console.nextDouble();
System.out.println("please enter your height in inches: ");
double Inputheight = console.nextDouble();
System.out.println("please enter your age in years: ");
double InputAge = console.nextDouble();
return BMIto(weight, height);
}
// Calculates BMI based on user inputs
public static double BMIto(double weight, double height){
return weight / Math.pow(height, 2);
}
// convert input height and weight to metric
public static String getConverted(double Metricconvert){
double Ht * kg;
double Wt * feet;
return getConverted;
}
// displays Users Health status based off of bmi
public static String getStatus(double bmi) {
if (bmi < 18.5) {
return "A BMI below the range 18.5 to 24.9 is considered underweight}
} else if (bmi < 25) {
return "A BMI in the range of 18.5 to 24.9 is considered normal";
} else if (bmi < 30) {
return "A BMI above range of 18.5 to 24.9 is considered overweight";
} else {
return "A BMI over 30 is obese";
}
}
}
public static double round(double value, int digits) {
return Math.round(value * Math.pow(10, digits)) / Math.pow(10, digits);
}
}
There are a number of issues with this piece of code, including the fact that it does not even compile. You've got a good number of syntax issues that are causing this.
For example, your local variable declarations inside method getConverted(double Metricconvert) are broken. I'm not sure exactly what the calculation you wanted should look like, however a more correct method definition would look like this (This is of course based off of the fact you have fields Ht and Wt, and that they should be class variables.
public static void getConverted(double Metricconvert) {
Ht = Metricconvert * kg;
Wt = Metricconvert * feet;
}
Another example of a syntactic error is an issue with one of your String return values (This one: A BMI below the range 18.5 to 24.9 is considered underweight). You've ended that return statement with a closing bracket, and it should be closed with a quotation mark ".
You should first fix the syntactical errors in this piece of code, and then work on the other issues, such as incorrect output.
So here is my task:
A postal company for a package charges $15 for the first
pound or a fraction thereof and $10 per pound for anything over one
pound. Write a program that prints the charge of a package.
Variables:
weight
First execution:
Weight? -12 Weight must be a positive number.
Second Execution:
Weight? 0 Weight must be a positive number.
Third Execution:
Weight? 2 Pay: $25.00
Forth Execution:
Weight? 2.8 Pay: $33.00
Fifth Execution:
Weight? 2.07 Pay: $25.70
and Here is the code I have developed so far:
import java.text.DecimalFormat;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
double weight;
double cost = 15.00; // set first pound to $15
double output = 0;
System.out.print("Weight?: ");
weight = keyboard.nextDouble();
if (weight <= 0) {
System.out.println("Weight must be a positive number.");
} else if (weight == 1) {
// Print the charge of the package
output = output + cost;
DecimalFormat money = new DecimalFormat("$0.00");
System.out.println("Pay: " + money.format(output));
} else {
for (double i = 1; i < weight; i = i + .01) {
if (weight > 1) {
output = output + (1 / 10.00);
}
}
// Print the charge of the package
output = output + cost;
DecimalFormat money = new DecimalFormat("$0.00");
System.out.println("Pay: " + money.format(output));
}
}
}
Everything works, but what I can't figure out is why (especially in the Fourth and Fifth Execution) is the final output always .10 cents off. Can anyone help me get to the accuracy I need?
Here is what I came up with:
Scanner keyboard = new Scanner(System.in);
double weight;
double cost = 15.00; // set first pound to $15
double output = 0;
System.out.print("Weight?: ");
weight = keyboard.nextDouble();
if (weight <= 0) {
System.out.println("Weight must be a positive number.");
} else {
// Print the charge of the package
if (weight > 1) {
output = cost + ((weight-1) * 10);
} else {
output = cost;
}
DecimalFormat money = new DecimalFormat("$0.00");
System.out.println("Pay: " + money.format(output));
}
This should handle all of your cases, as well as numbers between 0 and 1 assuming it's $1 per 0.1 lbs. Instead of your for-loop, you can just use the cost + ((weight-1) * 10) formula. I removed the check to see if weight was equal to 1 because it's handled in the else clause.
If I understand the question correctly, you should never have any fractional dollar amount because anything over a pound is automatically rounded up to the next pound. ie: 2.01 lbs would become 3 lbs. If this is correct, then you could use Math's ceil function to round the weight up to the nearest whole pound, then do something like this:
public class Main {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
double weight;
double cost = 15.00; // set first pound to $15
double output = 0;
System.out.print("Weight?: ");
weight = keyboard.nextDouble();
if (weight <= 0) {
System.out.println("Weight must be a positive number.");
} else if (weight == 1) {
// Print the charge of the package
output = output + cost;
DecimalFormat money = new DecimalFormat("$0.00");
System.out.println("Pay: " + money.format(output));
} else {
double temp = (Math.ceil(weight)) - 1;
for(double i = temp; i > 0; i-- ) {
output += 10;
}
output += cost;
DecimalFormat money = new DecimalFormat("$0.00");
System.out.println("Pay: " + money.format(output));
}
}
}
This way, you don't need to bother with 10 cent increments. I hope this helps. Let me know if you have any questions.
This: double i = 1; i < weight; i = i + .01 could be your problem.
Doubles are not exact for decimal math. You're expecting i == weight, at which point the loop should stop, but it might not because i + .01 (however many times) is a tiny fraction less than weight.
My advice is to ditch the loop. If the package is over 1 lb, just subtract one pound from the weight, multiply by the $10 per pound, and then round to the two decimal places you need (NOTE: round it according to how it's spec'd to be rounded, don't just let the conversion from double to decimal do it on its own. There are multiple ways to round something, and decimal does not magically know which one is right for your problem.)
EDIT: Look at your solution, is it supposed to only work to a resolution of 1/10 of a lb? If so, start by rounding the weight. Again, round it according to how it needs to be rounded (down, up, or nearest).