Imperial to kg converter - java

An exercise on my problem worksheet asks us to write a method public static double imperialToKg(double ton, double once, double drachm, double grain) that converts masses given in the imperial system to kg.
We've been given a conversion table for this but what I don't understand, being completely new to java, is HOW can I get my method to differentiate between these input arguments?
For example if I want the method to return the kg value of 11 stone what's to stop it from returning the value of 11 tons (tons being the first argument)
public class W1_E2{
public static double imperialToKg(double ton, double hundredweight, double quarter, double stone, double pound, double once, double drachm, double grain){
ton = 1016.04691;
hundredweight = 50.8023454;
quarter = 12.7005864;
stone = 6.35029318;
ounce = 0.02834952;
drachm = 0.00177185;
grain = 0.0000648;
}
}
I've listed the conversions as variables but I don't know what to do with them...

For 11 stone, you would have to call that like:
returnedFoo = imperialToKg(0,0,0,11,0,0,0);
If you want to call it with a value of 11 tons, you use:
returnedFoo = imperialToKg(11,0,0,0,0,0,0);
For our stone example, try:
On the implementation end, you would use something like:
public static double imperialToKg(double ton, double hundredweight, double quarter, double stone, double pound, double once, double drachm, double grain){
{
double kg = (ton * 1016.04691) + (hundredweight * 50.8023454) + (quarter * 12.7005864) + (stone * 6.35029318) + (ounce * 0.02834952) + (drachm * 0.00177185) + (grain * 0.0000648);
return kg;
}
This is quick and dirty; there is a multitude of better ways to do this, please confirm that the exercise is actually requesting we call the function like this.

Nowhere does it state that you require one method to make all your conversions, but that you require a main method to test your code.
So, make an individual method for each type of conversion required, as an example:
public static double tonToKg(double val){
return val * 1016.04691;
}
To test:
public static void main(String[] args){
System.out.println(tonToKg(11));
}

Related

Trying to multiply within the public static void. Any help is appreciated

So, for one of my homework pieces I have to make a Body Mass Index. When I asked my teacher about how to do math within the public void main, he explained that I could just do it in the void main. But when I try It gives me "The Operator * is undefined for the arguments type(s): String, Int".
Here's the code and Instructions:
(Instructions)
Create a new Java project named Your_Name_BMI. Create a class named BMI and write a program using JOptionPane dialog boxes that calculates and displays a person’s body mass index (BMI). The BMI is often used to determine whether a person with a sedentary lifestyle is overweight or under-weight for his or her height. A person’s BMI is calculated with the following formula:BMI = (weight*703) /(height2) Where weight is measured in pounds and height is measured in inches. The program should display messages to the user asking for their weight and height and store the values in appropriately named variables. After making the calculations the program should display a message indicating whether the person has optimal weight, is underweight, or is overweight. A sedentary person’s weight is considered optimal if his or her BMI is between 18.5 and 25. If the BMI is less than 18.5, the person is considered underweight. If the BMI value is greater than 25, the person is considered overweight.
import javax.swing.JOptionPane;
public class Doswell_BMI
{
//declaring important things
static String weight;
static String height;
static int multi;
static int multi2;
static String diagnosis;
static int bmi;
public static void main(String[] args)
{
weight= JOptionPane.showInputDialog("What is your weight?");
height= JOptionPane.showInputDialog("What is your height?");
multi = 703;
multi2 = 2;
bmi = weight * multi / height * multi2;
bmi = Integer.parseInt(diagnosis);
}
}
Yes, you can not multiply Strings as they are so you need to convert to an Integer first
int w = Integer.valueOf (weight);
String cannot be multiply, try this:
bmi = Integer.valueOf(weight) * multi / Integer.valueOf(height) * multi2;
I would advise against using ints to calculate BMI. The equation for calculating BMI in pounds and inches is as follows:
If you’re 5’5” (65”) in height and 150lbs in weight, you would calculate your BMI as follows:
(150lbs / (65 inches²)) x 703 = 24.96.
150 / 65*65 = 0.03550295858 <- This is the reason you want to be using a data type such as double.
weight= JOptionPane.showInputDialog("What is your weight?");
height= JOptionPane.showInputDialog("What is your height?");
These two statements return String values.
You cannot perform mathematical operations to string variables in JAVA.
Hence, you have to convert them to Integer using
either,
Integer.parseInt(weight)
this will convert the string into the primitive type int
or
Integer.valueOf(weight)
this will convert the string into an object of the wrapper class Integer
bmi = weight * multi / height * multi2;
This multiplication is not very accurate as your requirement above is to first multiply the two sections separately and then divide
It is better if you write this as bmi = (weight * multi) / (height * multi2)
so the final statement will be bmi = (weight.Integer.parseInt(weight) * multi) / (height.Integer.parseInt(height) * multi2)

JAVA Variable out of scope

I am a student, just learning about Class and Methods. I am receiving an error (line 30 - savings = pr * discount / 100) "Cannot find symbol". I understand that my variable discount, is out of scope, but I cannot figure out how to correct this. I have followed the instructions provided to me, but it still is not working. I have already caught a few typos in the textbook, so is there something missing? Or is it my positioning of curly brackets?
import java.util.Scanner; // Allows for user input
public class ParadiseInfo2
{
public static void main(String[] args)
{
double price; // Variable for minimum price for discount
double discount; // Variable for discount rate
double savings; // Scanner object to use for keyboard input
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter cutoff price for discount >> ");
price = keyboard.nextDouble();
System.out.print("Enter discount rate as a whole number >> ");
discount = keyboard.nextDouble();
displayInfo();
savings = computeDiscountInfo(price, discount);
System.out.println("Special this week on any service over " + price);
System.out.println("Discount of " + discount + " percent");
System.out.println("That's a savings of at least $" + savings);
}
public static double computeDiscountInfo(double pr, double dscnt)
{
double savings;
savings = pr * discount / 100;
return savings;
}
public static void displayInfo()
{
System.out.println("Paradise Day Spa wants to pamper you.");
System.out.println("We will make you look good.");
}
}
Your code is correct - you just called the out of scope variable discount when you needed the in scope variable dscnt. Try this:
public static double computeDiscountInfo(double pr, double dscnt) {
double savings;
savings = pr * dscnt / 100;
return savings;
}
The problem is caused by, as you mentioned in your question, the variable discount being out of scope. Let's look at why.
In your original code, the method computeDiscountInfo(double pr, double dscnt) is passed to parameters: a double labeled pr, and another double labeled dscnt. your method will only have knowledge of these two parameters, and not of anything going on outside of it. (There are some exceptions to this, such as 'static' variables, or variables passed from a parent. However, these are most likely beyond the scope of your learning at the moment. I'm sure you wil cover them in school soon.)
Since the variable discount is declared in the main() method, there is no way for your computeDiscountInfo(double pr, double dscnt) method to know of it's existence. When you cal on this method, you can pass it the discount variable as a parameter to be used (as you do in your code with savings = computeDiscountInfo(price, discount);) The method will then apply the value of discount to it's own local variable dscnt that you defined in the method's declaration. This is the variable that the method will know and use.
Now, lets look back at your method:
public static double computeDiscountInfo(double pr, double dscnt)
{
double savings;
savings = pr * discount / 100;
return savings;
}
In this method you refer to the variable as discount, not by the local name dscnt as declared in the method's parameters. The method has no understanding of what discount means. It could be passed any double in this place. By changing the word discount to dscnt inside your method, the method will be able to understand what you are reffering to and use the value properly.
public static double computeDiscountInfo(double pr, double dscnt)
{
double savings;
savings = pr * dscnt/ 100;
return savings;
}
I hope that this makes sense to you, please let me know if it does not. The concepts of local variables and variable scope is key parts of the foundation of Object-Oriented Programming.

Java decimal point in method

I am little bit lost with double decimal point at the moment.
I have basically two methods, which will set the values for double amount and double receive. Then another integer variable where I would like to set the (receive - amount) * 100.
For example if I have two double values and I want to set their difference to an int value, then would it be possible?
My problem is that if I try to find the difference between two values, then e.g. (10.0- 9.40), then it will be 0.599999999. How can I get 0.60 out of it inside the method and use it? I know how to use NumberFormat or DecimalFormat. Should I use one inside the method to set the number of decimal points?
you can round off the value im using a decimalformat to round off the number. You can pass a double variable inside the method and this will return a number rounded off to 2 decimal points.
double RoundTo2Decimals(double val) {
DecimalFormat df2 = new DecimalFormat("###.##");
return Double.valueOf(df2.format(val));
}
You can use BigDecimal to perform the rounding, or you can use maths like this. It basically multiplies by 100, rounds and divides by 100.
/**
* Performs a round which is accurate to within 1 ulp. i.e. for values very close to 0.5 it
* might be rounded up or down. This is a pragmatic choice for performance reasons as it is
* assumed you are not working on the edge of the precision of double.
*
* #param d value to round
* #return rounded value
*/
public static double round2(double d) {
final double factor = 1e2;
return d > WHOLE_NUMBER / factor || d < -WHOLE_NUMBER / factor ? d :
(long) (d < 0 ? d * factor - 0.5 : d * factor + 0.5) / factor;
}
Easiest solution could be below. Modifications and improvements are welcomed.
double x =10.0;
double y =9.40;
int xy =0;
DecimalFormat df = new DecimalFormat("#.##");
xy = (int) (Double.valueOf(df.format(x-y))*100);
System.out.println(xy);
I think I figured it out by using Math.round().
I will just ask whether my solution is a good or a bad idea to use? I am not just so familiar with BigDecimal. Long story short about the code. Example inputs are as: a = 9.40 and b = 10.0
private int difference;
private double amountDue;
private double receive;
public void setAmount(double a) {
amountDue = a;
}
public void receive(double b) {
receive = b;
difference = (int)Math.round(100 * (receive - amount));
I just needed to get int difference as 0.60 * 100 = 60, but as I mentioned before then just calculating the difference caused 0.59999999.
Just an extra question. Is it ok for me to initialize int balance variable inside one method as I have done?

Java - Costum Classes, code not working

For some reason when I run the file the answer seems to be 0. I'm still fairly new to Java so could someone explain to me what I've done wrong.. It all seems fine to me.
public class bus {
public static void main(String[] args) {
bus fivePM = new bus(23, 120);
bus elevenAM = new bus(27, 140);
System.out.println(fivePM.gallonsUsed());
System.out.println(elevenAM.gallonsUsed());
}
private int mpg;
private int milesTravelled;
private double used;
public bus(int mpg, int milesTravelled){
this.mpg = mpg;
this.milesTravelled = milesTravelled;
}
public double gallonsUsed(){
this.used = this.mpg/this.milesTravelled;
return this.used;
}
}
In both of your instantiated bus objects, milesTravelled is less than mpg.
When you divide an int by an int, you get an int.
this.mpg/this.milesTravelled;
This will return 0 because the digits after the decimal point don't matter if it's an int.
To make them not ints, you could do things like:
this.mpg * 1.0 / this.milesTravelled
or
this.mpg/((double) this.milesTravelled)
As mentioned, diving ints gives an integer number. You can change type types of mpg and milesTravelled to double. Also you should be inverting the answer. m/g divided by m = m/mg = 1/g, not g. For example, at 10mpg traving 20m would use 2 gallons, but your calculation would give 1/2 gallon.
Use double instead of int or just carefully convert your int into a double before doing any division. This is a common problem for Java novices. Take a look at this and this. Try this out:
private double mpg;
private double milesTravelled;
private double used;
public bus(double mpg, double milesTravelled){
this.mpg = mpg;
this.milesTravelled = milesTravelled;
}
NOTE 1: When you do the division, make sure you check to see if milesTravelled is equal to 0 or not. If it is, then you will get an Exception.
NOTE 2: Change bus to Bus in the header definition of bus (which then means you will use Bus instead of bus). Using the capital letter in the beginning of a custom Object's name is a relatively common standard.

Java double and working with really small values

I have to store the product of several probabilty values that are really low (for example, 1E-80). Using the primitive java double would result in zero because of the underflow. I don't want the value to go to zero because later on there will be a larger number (for example, 1E100) that will bring the values within the range that the double can handle.
So, I created a different class (MyDouble) myself that works on saving the base part and the exponent parts. When doing calculations, for example multiplication, I multiply the base parts, and add the exponents.
The program is fast with the primitive double type. However, when I use my own class (MyDouble) the program is really slow. I think this is because of the new objects that I have to create each time to create simple operations and the garbage collector has to do a lot of work when the objects are no longer needed.
My question is, is there a better way you think I can solve this problem? If not, is there a way so that I can speedup the program with my own class (MyDouble)?
[Note: taking the log and later taking the exponent does not solve my problem]
MyDouble class:
public class MyDouble {
public MyDouble(double base, int power){
this.base = base;
this.power = power;
}
public static MyDouble multiply(double... values) {
MyDouble returnMyDouble = new MyDouble(0);
double prodBase = 1;
int prodPower = 0;
for( double val : values) {
MyDouble ad = new MyDouble(val);
prodBase *= ad.base;
prodPower += ad.power;
}
String newBaseString = "" + prodBase;
String[] splitted = newBaseString.split("E");
double newBase = 0; int newPower = 0;
if(splitted.length == 2) {
newBase = Double.parseDouble(splitted[0]);
newPower = Integer.parseInt(splitted[1]);
} else {
newBase = Double.parseDouble(splitted[0]);
newPower = 0;
}
returnMyDouble.base = newBase;
returnMyDouble.power = newPower + prodPower;
return returnMyDouble;
}
}
The way this is solved is to work in log space---it trivialises the problem. When you say it doesn't work, can you give specific details of why? Probability underflow is a common issue in probabilistic models, and I don't think I've ever known it solved any other way.
Recall that log(a*b) is just log(a) + log(b). Similarly log(a/b) is log(a) - log(b). I assume since you're working with probabilities its multiplication and division that are causing the underflow issues; the drawback of log space is that you need to use special routines to calculate log(a+b), which I can direct you to if this is your issue.
So the simple answer is, work in log space, and re-exponentiate at the end to get a human-readable number.
You trying to parse strings each time you doing multiply. Why don't you calculate all values into some structure like real and exponential part as pre-calculation step and then create algorithms for multiplication, adding, subdivision, power and other.
Also you could add flag for big/small numbers. I think you will not use both 1e100 and 1e-100 in one calculation (so you could simplify some calculations) and you could improve calculation time for different pairs (large, large), (small, small), (large, small).
You can use
BigDecimal bd = BigDecimal.ONE.scaleByPowerOfTen(-309)
.multiply(BigDecimal.ONE.scaleByPowerOfTen(-300))
.multiply(BigDecimal.ONE.scaleByPowerOfTen(300));
System.out.println(bd);
prints
1E-309
Or if you use a log10 scale
double d = -309 + -300 + 300;
System.out.println("1E"+d);
prints
1E-309.0
Slowness might be because of the intermediate string objects which are created in split and string concats.
Try this:
/**
* value = base * 10 ^ power.
*/
public class MyDouble {
// Threshold values to determine whether given double is too small or not.
private static final double SMALL_EPSILON = 1e-8;
private static final double SMALL_EPSILON_MULTIPLIER = 1e8;
private static final int SMALL_EPSILON_POWER = 8;
private double myBase;
private int myPower;
public MyDouble(double base, int power){
myBase = base;
myPower = power;
}
public MyDouble(double base)
{
myBase = base;
myPower = 0;
adjustPower();
}
/**
* If base value is too small, increase the base by multiplying with some number and
* decrease the power accordingly.
* <p> E.g 0.000 000 000 001 * 10^1 => 0.0001 * 10^8
*/
private void adjustPower()
{
// Increase the base & decrease the power
// if given double value is less than threshold.
if (myBase < SMALL_EPSILON) {
myBase = myBase * SMALL_EPSILON_MULTIPLIER;
myPower -= SMALL_EPSILON_POWER;
}
}
/**
* This method multiplies given double and updates this object.
*/
public void multiply(MyDouble d)
{
myBase *= d.myBase;
myPower += d.myPower;
adjustPower();
}
/**
* This method multiplies given primitive double value with this object and update the
* base and power.
*/
public void multiply(double d)
{
multiply(new MyDouble(d));
}
#Override
public String toString()
{
return "Base:" + myBase + ", Power=" + myPower;
}
/**
* This method multiplies given double values and returns MyDouble object.
* It make sure that too small double values do not zero out the multiplication result.
*/
public static MyDouble multiply(double...values)
{
MyDouble result = new MyDouble(1);
for (int i=0; i<values.length; i++) {
result.multiply(values[i]);
}
return result;
}
public static void main(String[] args) {
MyDouble r = MyDouble.multiply(1e-80, 1e100);
System.out.println(r);
}
}
If this is still slow for your purpose, you can modify multiply() method to directly operate on primitive double instead of creating a MyDouble object.
I'm sure this will be a good deal slower than a double, but probably a large contributing factor would be the String manipulation. Could you get rid of that and calculate the power through arithmetic instead? Even recursive or iterative arithmetic might be faster than converting to String to grab bits of the number.
In a performance heavy application, you want to find a way to store basic information in primitives. In this case, perhaps you can split the bytes of a long or other variable in so that a fixed portion is the base.
Then, you can create custom methods the multiply long or Long as if they were a double. You grab the bits representing the base and exp, and truncate accordingly.
In some sense, you're re-inventing the wheel here, since you want byte code that efficiently performs the operation you're looking for.
edit:
If you want to stick with two variables, you can modify your code to simply take an array, which will be much lighter than objects. Additionally, you need to remove calls to any string parsing functions. Those are extremely slow.

Categories

Resources