a question on conversion logic - java

I am designing a unit converter using android.i m using logic which is not nice logic i think and i m giving some code here too.can anyone suggest me any better logic????
public void temperature(String value1,String value2)
{
if(value1.equals("Celsius") && value2.equals("fahrenheit") )
{
double i=Double.parseDouble(at1.getText().toString());
double value=i*33.8;
Double d=new Double(value);
at2.setText(d.toString());
}
else if(value1.equals("fahrenheit") && value2.equals("Celsius"))
{
double i=Double.parseDouble(at1.getText().toString());
double value=i*(-17.2222);
Double d=new Double(value);
at2.setText(d.toString());
}
There is like this many unit in every category like angle,computer.this is only a small example of temperature category.

Why not just
at2.setText(String.valueOf(Double.parseDouble(at1.getText().toString()) * 33.8);
Anyway, it's just to shorten your code, the logic stays the same.
P.S. Define some constants for values like 33.8 and -17.2222.

There's a lot of duplicated code in your example. Try to refactor it so you common actions are expressed only once.
Example:
public void temperature(String value1, String value2) {
double i = Double.parseDouble(at1.getText().toString());
double value;
if (value1.equals("fahrenheit") && value2.equals("celsius")) {
value = /* convert i */;
} else if (....) {
value = ...;
}
at2.setText(String.valueOf(value));
}
If your list of if statements becomes large, consider using a switch statement instead. You might want to change representation of the units from String to something else like integer constants or enums.

My suggestion would be to use the command pattern.
For temperature, I believe you can use Kelvin to convert to a common scale:
public class TemperatureConverter {
private final static String CELSIUS = "Celsius";
private final static String FARENHEIT = "Farenheit";
public double temperature(double temperature, String temp1Type, String temp2Type) {
Converter fromConverter, toConverter;
if (temp1Type.equals(CELSIUS)) {
fromConverter = new CelsiusConverter();
} else if (temp1Type.equals(FARENHEIT)) {
fromConverter = new FarenheitConverter();
} else {
fromConverter = new noopConverter();
}
if (temp2Type.equals(CELSIUS)) {
toConverter = new CelsiusConverter();
} else if (temp2Type.equals(FARENHEIT)) {
toConverter = new FarenheitConverter();
} else {
toConverter = new noopConverter();
}
return toConverter.fromKelvin(fromConverter.toKelvin(temperature));
}
}
Converter is an interface, and FarenheitConverter and CelsiusConverter are concrete classes that implement this interface. They contain the details to convert from Farenheit and Celsius (respectively) to Kelvin. They also contain the details of converting from Kelvin to their respective scales. This keeps the logic cleanly separated, and easily extended in the future.
Say in the future you need to convert from degrees blignox to degrees fizzbuzz. It's as simple as writing the BlignoxConverter and the FizzbuzzConverter, implementing the two methods, and plugging them in. Once they're written and integrated, you can convert from either of those to or from F and C as well.

Related

Java method taking 0 arguments and returning a double using if else statements with strings

I am trying to write a method which does not take any arguments and then returns a double variable. It is a postcode identifier so when a cost code is entered certain post codes need to return a double.
In my example below i need post codes that start with either "GH6 TXX" or "NC4 LXX". (X stands for any random character or digit) to return 50.0.
If any other postcode is entered then return 100.0.
However i am not getting any results back and just finding errors. I'm sure i have gone massive wrong somewhere as im not great with If Else statements within methods. Any help or knowledge on this would be great!
public class multiPostcodeRange {
//Declaring Variables
String pcode;
public multiPostcodeRange()
{
pcode = "XXX XXX";
}
public void multiPostcodeRange()
{
if (pcode("GH6 TXX", "NC4 LXX")) {
return 100.0; }
else {
return 50.0;}
} }
public class MultiPostcodeRange {
private String pcode;
public MultiPostcodeRange() {
pcode = "XXX XXX";
}
public double multiPostcodeRange() {
if (pcode.equals("GH6 TXX") || pcode.equals("NC4 LXX")) {
return 100.0;
}
else {
return 50.0;
}
}
}
To return double from a function you need to define a return type for the function.
public double multiPostcodeRange
You created a class with his methods (which btw you shouldn't name as the class, but give them unique names).
Then you have to create a new instance object of that class and call the method on a main function.
For example, at the end of your code:
`public static void main(String args[]){
multiPostcodeRange Obj = new
multiPostcodeRange();
Obj.meth1();
Obj.meth2();}`
NB remember to give those methods unique names!
Also change 2nd method body and type as AndyMan's answer

When and why to use a number as a String input?

I have been reading a java book where I came across a piece of code where a fake input is provided in order to test the main class. The fake input is a String and later converted into int primitive type using the Integer.parseInt() method. Following are the two classes:
The main class
public class SimpleDotCom{
int[] locationCells;
int numOfHits = 0;
public void setLocationCells(int[] locs){
locationCells = locs;
}
public String checkYourself(String stringGuess){
int guess = Integer.parseInt(stringGuess);
String result = "miss";
for(int cell : locationCells){
if(guess == cell){
result = "hit";
numOfHits++;
break;
}
}
if(numOfHits == locationCells.length){
result = "kill";
}
System.out.println(result);
return result;
}
}
The test class
public class SimpleDotComTestDrive{
public static void main(String[] args){
SimpleDotCom dot = new SimpleDotCom();
int[] locations = {2,3,4};
dot.setLocationCells(locations);
String userGuess = "4";
String result = dot.checkYourself(userGuess);
}
}
I tried the same example with an int variable and it worked:
public class DotCom{
int[] locationCells;
int numOfHits = 0;
public void setLocationCells(int[] locs){
locationCells = locs;
}
public String checkYourself(int stringGuess){
//int guess = Integer.parseInt(stringGuess);
int guess = stringGuess;
String result = "miss";
for(int cell : locationCells){
if(guess == cell){
result = "hit";
numOfHits++;
break;
}
}
if(numOfHits == locationCells.length){
result = "kill";
}
System.out.println(result);
return result;
}
}
public class DotComTestDrive{
public static void main(String[] args){
DotCom dot = new DotCom();
int[] locations = {2,3,4};
dot.setLocationCells(locations);
int userGuess = 4;
String result = dot.checkYourself(userGuess);
//System.out.println("result2 = "+result);
}
}
I understand the code, but the question is why to have an input as a String where as the same result can be achieved by using an int variable.
I am not sure if I am missing something in understanding or may be my question is completely wrong, but as I tried the same example with an int variable and it worked, I keep wondering when and why to have inputs as a String?
Internally in your program it is recommended to use the strongest possible type, in your case use the int.
But your program has an outside border where data come in and go out, like user input, feedback on the console, I/O operations to files or network, etc. In many cases you have to convert the involved data to or from types which are defined by the interface specification. An XML or json structure transports each data as a string, including numbers and dates. As soon as it passes the border of your application it should be immediately converted to the internally used type (and - of course - checked if the conversion is valid).
The background to this is: Serializing and deserializing (network streams, files) is easier done (better interchangable) using strings. But inside a process (by the CPU) it is better to operate on binary representations of the data.
If the number is large enough and can't be inside the integer or long range.
Also, beneficial for solving these problems in an efficient way
1) When you want to check if a number is a palindrome or not in an
efficient way.
2) When you want to know digits of the number without division
operator.
Few examples Which I am able to recollect now.

ArrayList<Object> how to differentiate objects added

the question is the same as in the title. i have arraylist to which i add incomes or expenses both in form of a object. will this loop sum up all elements, and is there a better way of doing this :?
public void sumOfAllExpAndIn(){
int tmp = 0;
for (Iterator<Object> it = database.iterator(); it.hasNext();){
if (it.next() instanceof Expenses){
Expenses excalc = new Expenses();
excalc = (Expenses) it.next();
tmp -= excalc.value;
}
else {
incomes incalc =new incomes();
incalc = (incomes) it.next();
tmp += incalc.value;
}
}
System.out.format("the overall balance is %d",tmp);
}
Yes there are several better ways of doing it.
Firstly, I don't suggest you declare it as an Object list. Better is to declare an interface and then implement the interface in each of your classes:
interface BudgetValue {
double getValue();
}
class Expense implements BudgetValue {
public double getValue() {
return -value;
}
}
class Income implements BudgetValue {
public double getValue() {
return +value;
}
}
Then you can declare list of BudgetValues rather than Objects as the input to your method:
double sumBudgetValues(List<BudgetValues> budgetValues) {
}
There are two easy ways of summing them:
double total = 0.0;
for (BudgetValue value: budgetValues) {
total += value.getValue();
}
return total;
or using Java 8:
return budgetValues.stream()
.mapToDouble(BudgetValue::getValue)
.sum().orElse(0.0);
The streams method makes a lot more sense to me and allows it to be easily multithreaded if you have a lot of values to sum by turning it into a parallel stream.
There are some rare occassions where instanceof is justified but, as a rule of thumb, if you find yourself using it then start by asking yourself whether there's an interface missing.
I suggest making your Expenses and Incomes classes implement a common interface, for example LineItem. Now if you use signed values (positive for incomes and negatives for expenses), you only have to call getValue() on any implementation of LineItem and add it to your running total... no if/else needed, no collection of Object needed.
public void sumOfAllExpAndIn(){
int tmp = 0;
for (Iterator<LineItem> it = database.iterator(); it.hasNext();){
tmp += it.next().getValue();
}
}
System.out.format("the overall balance is %d",tmp);
}

How to change code that uses many if statements to choose a class by name?

I'm working on a program to simulate an RLC circuit. The program makes some specific calculations based on the type of circuit and type of source (RLC, LC, RC ,sinusoidal, DC, square ...) which later are added to Charts.
The following code works the way I need it to, but my teacher told me that it will be better if I make an individual class for every case, because too many if statements are not good.
if(scheme == "RLC"){
beta = R / (2*L);
omega0Square = 1/ (L*C);
//Resonant
if (omega * omega == omega0Square
&& beta >= Math.sqrt(omega0Square) / Math.sqrt(2)){
chargeAmp = U0 / (L*2*beta*Math.sqrt(omega0Square - beta*beta));
fi = Math.atan(Math.sqrt(omega0Square-2*beta*beta)/beta);
}
//Non-resonant
else{
omegasDifference = (omega0Square - omega * omega);
fi = Math.atan(2 * beta * omega / omegasDifference);
chargeAmp = U0/(L*Math.sqrt(omegasDifference * omegasDifference
+ 4 * beta * beta * omega * omega));
}
intensity = chargeAmp*omega* Math.cos(omega*time-fi);
rU = R * intensity;
cQ = chargeAmp*Math.sin(omega*time-fi);
lE = L*intensity*intensity/2;
}
if(scheme == "LC"){
}
if(scheme == "RC"){
}
if(scheme == "R"){
}
if(scheme == "L"){
}
if(scheme == "C"){
}
if(scheme == "Non"){
}
If I made a class for every case, how can i manage them later, and invoke them without using if statements? I thought about something like this:
String name;
name variable = new name();
Is it possible? Or is there a better way?
Use Interfaces and factory pattern
Create a class to hold the values ( R,L,C)
public class RLCHolder {
double rValue;
double lValue;
double cValue;
//Setter and Getters
}
Create an Interface
public interface CircuitCalculator {
public double calculate(RLCHolder rlcHolder);
}
Now implement the Interface
public class RLCCircuitCalculator implements CircuitCalculator {
#Override
public double calculate(RLCHolder rlcHolder) {
// Do you Math and Return
return 0;
}
}
Like this add your implementation for other Circuits like.
LCCircuitCalculator , RCCircuitCalculator and so
Now create Factory method and call the calculate method
public class Calculator {
// factory method
public static CircuitCalculator getCircuitCalculator(String circuitName){
CircuitCalculator circuitCalculator = null;
if (circuitName.equals("RLC")){
circuitCalculator = new RLCCircuitCalculator(); // You can cache if you dont maintain state
}else if (circuitName.equals("LC")){
// return LC object
}//add your implementation..
return circuitCalculator;
}
public static void main(String args[]){
RLCHolder rlcHolder = new RLCHolder();
double result = Calculator.getCircuitCalculator("RLC").calculate(rlcHolder);
}
}
Since you have different circuit i don't think you can really escape from using if statement or more elegant way you can use switch. What your teacher mean by creating seperate class for each circuit its because he want you have small chunk of code inside your if statement if you start coding like the way you code right now it will be a huge function.

How can I improve this block of code?

public class OrderProcessor {
public Double calculateTotalPriceWithDiscountCode(Order order,
char discountCode) {
Double itemTotal = order.getItemTotal();
Double discountAmount = 0.0;
switch (discountCode) {
case 'A':
discountAmount = 0.95 * itemTotal;
break;
case 'B':
discountAmount = 0.15 * itemTotal;
break;
}
return itemTotal - discountAmount;
}
Current implementation in order processor is closed for extension and open for modification for adding new discount codes, how can i improve the design to get rid of this limitation
In general, the presence of a switch is a pretty good giveaway as to what should be a class instead. So, a first stab at it would be something like this:
public interface Discounter {
public double applyDiscount(double itemTotal);
}
public class OrderProcessor {
private Map<Char, Discounter> discounts = new HashMap<Char, Discounter>();
public void addDiscounter(Char discountCode, Discounter discounter) {
discounts.put(discountCode, discounter);
}
public Double calculateTotalPriceWithDiscountCode(Order order, char discountCode) {
double itemTotal = order.getItemTotal();
double discountAmount = 0.0;
if (discounts.hasKey(discountCode))
discountAmount = discounter.applyDiscount(itemTotal);
return itemTotal - discountAmount;
}
}
This would then be extended through something like this:
processor.addDiscounter('A', new Discounter() {
public double applyDiscount(double itemTotal) {
return 0.95 * itemTotal;
}
});
You could make a remove method as well, and then your discounters can become more complex, consulting external data, etc. You may want to open up the interface a bit and pass in the whole order for more examination.
Note: If this is something you're going to be doing in production I have two pieces of unsolicited advice:
Consider using something like JBoss Drools to handle your business logic instead of this; it's a lot more powerful and flexible.
Please don't use double for actual financial calculations. :)
As you have pointed out that the discount code needs to be changeable, it is best to separate out the actual discount codes from the code. Maintain the discount codes in an xml or settings file and lazy load the values into a dictionary/hashset before using them.
For example your xml could look like this,
<Discounts>
<Discount code="A" value="0.05"/>
<Discount code="B" value="0.10"/>
<Discount code="C" value="0.15"/>
</Discounts>
In your calculateTotalPriceWithDiscountCode, populate a dictionary with the values read from this xml.
if(discountsDictionary == null)
{
discountsDictionary = LoadValuesFromXml(xmlFilePath);
}
In case your discounts xml is likely to change during program execution then perform the Load operation when you want the discount value (as compared to loading once in the above code fragment).
Then access the code (key) to retrieve the discount (value),
if(discountsDictionary.ContainsKey(discountCode))
{
discount = discountsDictionary[discountCode];
discountedItemPrice = itemPrice * ( 1 - discount);
}
else
{
// Invalid discount code...
}
Pull the logic for calculating totals based on an order into its own class/interface:
class OrderProcessor {
// Probably inject this or load it some other way than a static factory
private Collection<TotalCalculator> calculators = TotalCalculatorFactory.getTotalCalculators();
public Double calculateTotalPriceWithDiscountCode(Order order, char discountCode) {
for (TotalCalculator calculator : calculators) {
if (calculator.supports(discountCode)) {
return calculator.calculateTotal(order);
}
}
return order.getItemTotal();
}
}
class TotalCalculator {
private char discountCode;
private double discountRatio;
public TotalCalculator(char discountCode, double discountRatio) {
this.discountCode = discountCode;
this.discountRatio = discountRatio;
}
public boolean supports(char discountCode) {
return this.discountCode == discountCode;
}
public Double calculateTotal(Order order) {
return order.getItemTotal() - order.getItemTotal() * discountRatio;
}
}
class TotalCalculatorFactory {
public static Collection<TotalCalculator> getTotalCalculators() {
return Arrays.asList(
new TotalCalculator('A', 0.95),
new TotalCalculator('B', 0.15)
);
}
}
In a real system, I'd make the TotalCalculator an interface, which would have the additional advantage of being able to calculate order totals in other ways than just a percentage discount reduction.
This solution is also very flexible in allowing you to create your TotalCalculators (or implementations if an interface) using other mechanisms than manually coding them into a factory. You can use an IoC container to create and inject them or use a ServiceLoader to find and load them, for example.
My idea is maintain discounts separately.
public class OrderProcessor {
public Double calculateTotalPriceWithDiscountCode(Order order,
char discountCode) {
Double itemTotal = order.getItemTotal();
return itemTotal - (itemTotal* Discounts.GetDiscounts(discountCode));
}
}
////////////////
class Discounts
{
public static double GetDiscounts(char discountCode)
{
switch (discountCode) {
case 'A':
return 0.95d;
case 'B':
return 0.15d;
default:
return 0.00d;
}
}
}
In this calculateTotalPriceWithDiscountCode function, it is not a good idea to pass a discount code as parameter. Well, 3rd person , who review your code , would not understand would not understand what does it mean except you, a kind of code smell.
One of a suggestion is that you need to create another class called Discount, and you pass the Discount object as a parameter, and you get the internal value from its public method.
i.e.
public class Discount {
//Use a hash map to store your Code associate with your discountAmount
public Discount(char discountCode){
this.discountCode = discountCode
}
public int getDiscountAmount(){
....
....
}
}
Right now, what you actually need to modify will be the Discount Class only, and your calculateTotalPriceWithDiscountCode will not need to care.
You could use a separate xml file for storing codes as well as their calculation mechanishms.
This will remove the limitation of inablility to add new discount code.
XML File: discounts.xml
<discount-codes>
<discount-code>
<code>A</code>
<val>0.15</val>
</discount-code>
<discount-code>
<code>B</code>
<val>0.95</val>
</discount-code>
</discount-codes>
Note: Operation code (What am I intended to do with the values?) is not currently implemented. You can implement the same at your end.
Use an XML parser class:
Class: DiscountModel.java (This class is the model to store the discount codes)
public class DiscountModel {
char code;
Double val;
// Implement getters and setters
}
Class: DiscountParser.java (This will parse the discounts.xml file and store the codes in a list)
public class DiscountParser {
List<DiscountModel> discountsList;
// Getters and Setters for discountsList
// Parser Code
public void parseDiscounts() {
// Code here
}
// Add new discount
public void addDiscount() {
// Code
}
// Remove discount
public void removeDiscount () {
// Code
}
}
Class: OrderProcessor.java (This will bring out the discounted value after calculation)
/**
* Call this class when calculations need to be done.
*/
public class OrderProcessor {
// Declare instance of DocumentParser
DocumentParser dc1;
// Getter and setter for dc1
public Double calculateTotalPriceWithDiscountCode(Order order, char discountCode) {
// Find the corresponding discountcode and
// value from the list of values in the
// Class DocumentParser
// Use the corresponding values to calculate
// the discount and return the value
}
}
Whenever a new code is to be added, you can insert the same to the xml file. The same applies if the discount code needs to be removed.
Hope the above helps.

Categories

Resources