I'm making a program that find sums multiple values that are in a single string. For example you put H2O in and it will return the molar mass value for that chemical (2*H + O). So I copied the periodic table and listed the values e.g "private double H = 1.008;". So the problem is I need to get that value based on the name of the variable. Here is an example.
private double H = 1.008;
System.out.println(multMass(2, H));
// should print 2.016
public static double multMass(int multiplier, String chem){
return double(chem) * multiplier;
} /\
||
where the double would go(in this case 'double H')
Don't use raw variables for this. Use a Map instead:
Map<String, Double> elemWeights = new HashMap<>();
// Associate an element symbol and a weight
// This would be your "double H = 1.008"
elemWeights.put("H", 1.008);
elemWeights.put("Li", 6.94);
...
public static double multMass(int multiplier, String chem) {
double weight = elemWeights.get(chem); // And do a lookup
return weight * multiplier;
}
Or, a little neater:
Map<String, Double> elemWeights = Map.ofEntries(
entry("H", 1.008),
entry("Li", 6.94)
...
);
Or see here for other ways this can be written based on the version of Java that you're using.
Related
I have an object that follows the structure below
class Ray{
float param1;
float param2;
}
and then I have the following: List<Ray> rays
I have a 2D slider that gives a couple of values {value1, value2}
The problem is that the values inside the slider are continuous and they don't match exactly with the values of the class Ray, thus I cannot just make a filter using stream().
I need to find the Ray that has both fields closest to value1 and value2.
I'm not really expert using streams().
My first idea is to iterate the List and find the nearest value (let's say nearestParam1) to value1, then iterate the list and find the nearest value (nearestParam2) to value2, then filter the list by nearestParam1 and finally filter the list by nearestParam2.
...
List<Ray> rays;
float nearestParam1;
float value1;
float oldDistance=9999;
for (Ray ray : rays){
float newDistance = abs( ray.Param1 - value1);
if(newDistance < oldDistance) {
oldDistance = newDistance;
nearestParam1 = ray.Param1;
}
}
List<Ray> filteredRays = rays.stream().filter(ray -> ray.Param1 == nearestParam1).toList();
and then repeat again for the second field. I don't like this solution, can you find a cleaner and maybe faster solution?
My list has a really huge dimension and inside there are not equals object (1 field could match but not both at the same time)
Rather than comparing each field separately, you can consolidate them into a single value and then find the closest one to your target date using Stream#min.
public LocalDateTime toDateTime(int dayOfTheYear, double timeOfTheDay) {
LocalDate first = LocalDate.of(2022,1,1);
return first.atStartOfDay()
.plusDays(dayOfTheYear)
.plusHours((int) timeOfTheDay)
.plusMinutes((long) ((timeOfTheDay - Math.floor(timeOfTheDay)) * 60L));
}
public Optional<Ray> findClosestRay(List<Ray> rays, int DayOfTheYear, float TimeOfTheDay) {
LocalDateTime target = toDateTime(DayOfTheYear, TimeOfTheDay);
return rays.stream()
.min(Comparator.comparing(ray -> Duration.between(target, toDateTime(ray.DayOfTheYear, ray.TimeOfTheDay)).abs()));
}
as MikeFHay pointed out in the main post i didn't specified how to determine the single closest result over all rays combining minimization of param 1 and param 2.
I found a solution that is quite working for my case, what do you think about that?
Comparator<Ray> comparator = Comparator.comparing(ray->abs(ray.param1-value1) + abs(ray.param2-value2) );
Ray bestRay = rays.stream().min(comparator).get();
I am having issues with the output of my code. Seems I am missing something in my method that I created... I had instructions to return the total number of inches. I places totInches after return and get an error stating that totInches is not a variable. Not certain what is missing here as I am only supposed to be creating a method. Most of this code was written and the only portion I was supposed to created was the second convertToInches method.. Any advice?
import java.util.Scanner;
public class FunctionOverloadToInches {
public static double convertToInches(double numFeet) {
return numFeet * 12.0;
}
public static double convertToInches(double numFeet, double numInches) {
return totInches * 12.0;
}
public static void main (String [] args) {
double totInches = 0.0;
totInches = convertToInches(4.0, 6.0);
System.out.println("4.0, 6.0 yields " + totInches);
totInches = convertToInches(5.9);
System.out.println("5.9 yields " + totInches);
return;
}
}
The variable totInches is not defined in the scope of your function:
public static double convertToInches(double numFeet, double numInches) {
return totInches * 12.0;
}
The only variables you can use in this function are the ones you create and the ones defined as formal parameters: numFeet and numInches. So you have to come up with an equation that takes numFeet and converts it to inches, taking into account the additional inches provided in numInches.
You declared the double variable "totInches" inside of your main method, but you are trying to access it inside of your "convertToInches" method. When declaring a variable in a particular method, that variable is ONLY accessible by that method. Your "convertToInches" knows of only two variables: numFeet and numInches, which you passed to it in the parameter. It then looks at your return statement, sees "totInches" and has no idea what it is.
I also don't understand what this is trying to do...
public static double convertToInches(double numFeet, double numInches) {
return totInches * 12.0;
}
Why are you passing it the double variables numFeet and numInches? The function isn't using them. I also don't understand why you need both the number of feet AND the number of inches if the method, by its name, is trying to convert something into inches.
public static double convertToInches(double numFeet, double numInches) {
return (numFeet * 12) + numInches;
This takes into account any variable amount entered by user for height of 5 feet 7 inches or 6 feet even
Say, for example, I have a double variable in Java:
double alpha = 3;
However, I wanted to create a String variable, including that Double Variable:
String beta = "Alpha has a value of " + alpha;
So that the output would be
//Output
Alpha has the value of 3
However, it will not let me do so, as it says the double value cannot be included in the string value.
As I am doing this for around 150 variables, I want to know how to do it the simplest and shortest way.
Thanks
I am doing this for around 150 variables
A common way of simplifying a repeated task is defining a helper method for it:
String description(String name, Object obj) {
return name + " has a value of " + obj;
}
Now you can use it like this:
String beta = description("Alpha", alpha);
Doing this for 150 variables sounds suspicious - chances are, you have an opportunity to make an array. You can define an array of names, then pair them up with values, like this:
String[] names = new String[] {
"Alpha", "Beta", "Gamma", ...
}
double[] values = new double[] {
1.2, 3.4, 5.6, ...
}
for (int i = 0 ; i != names.length() ; i++) {
System.out.println(description(names[i], values[i]));
}
You can use Double.toString(double).
String beta = "Alpha has a value of " + Double.toString(alpha);
When you need to convert a double to a string, use
Double.toString(double);
Where double is the name of the variable.
I have developed a program that solves kinematic equations in elementary physics. To solve, one needs 3 out of a possible 5 variables. There are 10 different combinations of what 3 variables are known. I coded 10 scenarios similar to the two blocks of code below
// If we have acceleration, final velocity, and initial velocity
if (varEntered[0] == true && varEntered[1] == true && varEntered[2] == true)
{
double acceleration = knownVariables[0]; //Setting acceleration
double finalVelocity = knownVariables[1]; //Setting finalVelocity
double initVelocity = knownVariables[2]; //Setting initVelocity
double time = ((finalVelocity - initVelocity)/acceleration); //Finding time using an equation
double distance = ((finalVelocity + initVelocity)*((0.5)*time)); //Finding distance using an equation
System.out.println("The time is " + time + " seconds"); //Printing time
System.out.println("The distance is " + distance + " meters"); //Printing distance
}
//If we have distance, final velocity, initial velocity
if (varEntered[3] == true && varEntered[1] == true && varEntered[2] == true)
{
//Known variables
double distance = knownVariables[3]; //Acceleration
double finalVelocity = knownVariables[1]; //Final Velocity
double initVelocity = knownVariables[2]; //Initial Velocity
// Unknown variables
double time = (distance/((0.5)*(finalVelocity + initVelocity))); //Time
double acceleration = ((finalVelocity - initVelocity)/time); //Acceleration
System.out.println("The time is " + time + " meters/second"); //Printing time
System.out.println("The acceleration is " + acceleration + " meters/second^2"); //Printing distance
}
These seem very similar, but are different scenarios. As a programming beginner, I am wondering if the algorithm I use can be modified to shorten the code. If any more info is needed I will be more than happy to provide.
You should define a function that accepts three numbers and performs the general calculation.
For a starter, try this tutorial. Then you can call your function twice, each time with different sets of variables.
I would use a Map and do something like this (warning: pseudocode):
import java.util.HashMap;
import java.util.Map;
Map<String,double> map=new HashMap<String, double>();
Initialize the map with all the values that are known, e.g.:
map.put("initVelocity", 0.35);
Then you can define the following function:
void calculateValues(Map<double,String> map){
if( map.containsKey("initVelocity") && map.containsKey("finalVelocity") && map.containsKey("acceleration")){
map.put("time",((map.get("finalVelocity") - map.get("initVelocity")/map.get("acceleration"));
}
add all the other algorithms here in the same way!!!
}
This function takes the values that are already defined in the HashMap and tries to calculate the missing parameters. It will often be necessary to call it multiple times on a map until all parameters are set. You could do something like:
while( the map has not all values set){
calculateValues(map);
}
Also, you could make sure (by adding this condition to the if-statements) that any of the algorithms is called only if the resulting values are not set yet. But don't worry too much about that.
From what I noticed, it seems each variable is associated with a number. You can eliminate all the possible scenarios completely and have if conditions on each of the five variables; through this identify the 3 variables first and initialize the local variables. They are independent of each other when assigned, so there's no reason to make that many combinations. This will shorten the code by a lot.
The next step is to shorten the number of combinations you have. The best thing I can think of is finding out the two values you need to compute and using the formulas, in other words another block of if else statements. Here's what the code would look like:
//initialize all to 0
double acceleration = 0;
double distance = 0;
double finalVelocity = 0;
double initVelocity = 0;
double time = 0;
//place the proper values for each
if (varEntered[0] == true){
acceleration = knownVariables[0];
}
if (varEntered[1] == true){
finalVelocity = knownVariables[1];
}
if (varEntered[2] == true){
initVelocity = knownVariables[2];
}
if (varEntered[3] == true){
distance = knownVariables[3];
}
if (varEntered[4] == true){
time = knownVariables[4];
}
// now you have 10 cases
if(varEntered[0] == false && varEntered[1] == false){
//use the formulas here
} else if (varEntered[0] == false && varEntered[2] == false){
//use other formula here
}// repeat for the next 8, with each time you change the condition and formulas
//like you have it. Also, I noticed that you missed the else in your conditionals;
//it is more efficient if you use if-else clauses when only one should execute every time you run the code.
Hope this helps.
Feel free to copy this out, fill the rest and try it out.
If you're careful with your dependencies, you can get away with 5 cases with 1 calculation each instead of 10 cases with 2 calculations each. To do this, you have to make sure that no two variables directly depend on each other. If that were to happen, then you would be out of luck when both of the variables are unknown.
One way to do this is to take your list of variables and calculate each variable in terms of the following three (wrapping around when you reach the end of the list), as in the following example. In this example, solveAll takes an array of doubles with the unknowns set to Double.MAX_VALUE, and it sets the unknowns to the correct values. (If there are more than two unknowns, you'll get an infinite recursion.)
// Really should use enum instead of constant ints, and an EnumMap instead of an array.
public final static int ACCELERATION = 0;
public final static int FINALVELOCITY = 1;
public final static int INITVELOCITY = 2;
public final static int DISTANCE = 3;
public final static int TIME = 4;
private double[] vars;
public void solveAll(double[] vars) {
this.vars = vars;
for (int i=ACCELERATION; i<=TIME; i++) {
get(i);
}
}
private double get(int v) {
if (vars[v] != Double.MAX_VALUE) {
return vars[v];
}
switch (v) {
case ACCELERATION:
return (vars[ACCELERATION] = (get(FINALVELOCITY)*get(FINALVELOCITY) - get(INITVELOCITY)*get(INITVELOCITY)) / (2*get(DISTANCE)));
case FINALVELOCITY:
return (vars[FINALVELOCITY] = 2*get(DISTANCE)/get(TIME) - get(INITVELOCITY));
case INITVELOCITY:
return (vars[INITVELOCITY] = get(DISTANCE)/get(TIME) - get(ACCELERATION)*get(TIME)/2);
case DISTANCE:
return (vars[DISTANCE] = (get(FINALVELOCITY) - get(ACCELERATION)*get(TIME)/2) * get(TIME));
case TIME:
return (vars[TIME] = (get(FINALVELOCITY) - get(INITVELOCITY)) / get(ACCELERATION));
}
return Double.MAX_VALUE; // Bad variable index
}
I have some constants f.e.:
BigDecimal ceiling1 = new BigDecimal(5);
BigDecimal ceiling2 = new BigDecimal(10);
BigDecimal ceiling3 = new BigDecimal(20);
BigDecimal rate1 = new BigDecimal(0.01);
BigDecimal rate2 = new BigDecimal(0.02);
BigDecimal rate3 = new BigDecimal(0.04);
BigDecimal rate4 = new BigDecimal(0.09);
Now based on a parameter f.e.:
BigDecimal arg = new BigDecimal(6);
I want to retrieve the right rate which is based on this if structure (simplified):
if(arg <= ceiling1) {
rate = rate1;
}else if(arg <= ceiling2) {
rate = rate2;
} else if (arg <= ceiling3) {
rate = rate3;
}else rate = rate4;
So in my example rate should be rate2
But I'm wondering if someone knows a better way to implement this, instead of a bunch of ifs.
Any pointers are welcome!
PS: I know my code isn't 100% right, just wanted to show the idea
You can store your ceilings as keys in a TreeMap and your rates as values. Then use floorEntry and see also here.
final TreeMap<BigDecimal, BigDecimal> rates = new TreeMap<BigDecimal, BigDecimal>();
rates.put(new BigDecimal(0), new BigDecimal(0.01));
rates.put(new BigDecimal(5), new BigDecimal(0.02));
rates.put(new BigDecimal(10), new BigDecimal(0.04));
rates.put(new BigDecimal(20), new BigDecimal(0.09));
System.out.println(rates.floorEntry(new BigDecimal(0)).getValue());
System.out.println(rates.floorEntry(new BigDecimal(6)).getValue());
System.out.println(rates.floorEntry(new BigDecimal(10)).getValue());
System.out.println(rates.floorEntry(new BigDecimal(100)).getValue());
Test: http://ideone.com/VrucK. You may want to use a different representation as you can see in the test it looks ugly(Like Integers for the ceiling). Btw the ugly output comes from the fact that 0.01 is a double which does funny things with decimal representations.
Edit: Suggested cleanup.
I would probably get rid of the BigDecimal objects and store the rates (and the ceilings) as CONSTANTS (FINAL variables).
Then i will use a Switch statement to find the right rate.
class RateCalculator {
double ceiling[] = new double[]{5,10,20};
double rate[] = new double[]{0.01,0.02,0.04}
// use assertions to ensure that the sizes of these two arrays are equal.
// ensure that successive values in ceiling are higher than the last.
public double calculateRate(double value) {
for (int i=0;i<ceiling.length;++i) {
if (value < ceiling[i]) {
return rate[i];
}
// the rate for values higher than the highest ceiling
return 0.09;
}
}
You can change the number of rates by changing the size of the arrays. Some of the values should be named constants to follow good programming style - they are left as numbers here to illustrate the correspondance between the OPs values and the ones here.
Conversion to BigDecimal is left as an exercise for the reader.