#####################################################
Sample Solution to Lab2 Problems
#####################################################
Problem ->
1. Older computers used Binary Coded Decimals (BCD) to represent integers. In this each digit is
represented by using 4 bits. So 0 is 0000, 1 is 0001, 2 is 0010, ... 9 is 1001. The remaining 4 bit patterns, namely 1010 onwards are illegal. So 32 bits can store upto 8 digits. To represent a 
negative number the sign is also encoded using 4 bits. However, we are interested only in positive
BCD numbers. For example assuming we have 32 bits the number 123 will be represented as (0000) 5 
times followed by 000100100011. 
Define a class BCD with a single constructor which takes an int argument and creates its BCD 
equivalent. Write methods for adding, subtracting, multiplying and dividing BCD numbers. Also, 
write methods to check for <, > and == between two BCD numbers. 
							                                     [15]
Solution ->
public class BCD{
	
	static final int NO_OF_NYBBLES = 8;
	int[] nybble = new int[NO_OF_NYBBLES];	
	//Constructors
	public BCD(){
		int i;
		for( i = 0; i < NO_OF_NYBBLES; i++ )
			nybble[i] = 0;
	}
	
	public BCD(int i){
		int j;
		int val = i;
		for( j = NO_OF_NYBBLES - 1; j >= 0; j-- ){  
			nybble[j] = val % 10;
			val = val / 10;
		}	
	}
	public BCD(BCD b){
		int i;
		for( i = 0; i < NO_OF_NYBBLES; i++ )
			nybble[i] = b.getNthNybble(i);
	}
	
	
	//Get the BCD digit at nth position
	
	public int getNthNybble(int n){
		return nybble[n]; 
	}
	//Set BCD digit at nth position
	
	public void setNthNybble(int n, int val){
		nybble[n] = val;
	}
	
	
	//Convert BCD from internal representation to String
	
	public String toString(){
		String s = new String("");
		int i;
		for( i = 0; i < NO_OF_NYBBLES; i++ ){
			Integer iNybble = new Integer(nybble[i]);
			s += iNybble.toString();
		}
		return s;
	}
	//Convert BCD from internal representation to integer
	public int toInteger(){
		int i, factor = 1, sum = 0;
		if ( nybble[0] == 15 ) return -1;
		
		for( i = NO_OF_NYBBLES - 1; i >= 0; i--){
			sum += nybble[i] * factor;
			factor = factor * 10;
		}
		return sum;
	}
	
	
	//Make a copy of this BCD object
	
	public BCD copy(){
		BCD bcdcopy = new BCD(0);
		int i;
		for( i = 0; i < NO_OF_NYBBLES; i++ )
			bcdcopy.setNthNybble(i, nybble[i]);
		return bcdcopy;	
	}
	
	// Add 2 BCD nos and return BCD sum
	
	public BCD add(BCD bcd2){
		BCD bcdsum = new BCD(0);
		int i, tempsum, carry = 0;
		static final int MASK = 15; 
		
		for( i = NO_OF_NYBBLES - 1; i >= 0; i-- ){	
			tempsum = nybble[i] + bcd2.getNthNybble(i) + carry;
			
		/*If sum of 2 BCD digits is > 9, need to add 6
		  to it to bring it back to correct sum. In this
		  case, there's a carry to next 4 bits*/
		  
			if ( tempsum > 9 ){
				carry = 1;
				tempsum = (tempsum + 6) & MASK;
			}	
			else
				carry = 0;
			bcdsum.setNthNybble(i, tempsum);
		}	
		return bcdsum;		
	}
	
	// Subtract 2 BCD nos and return difference
	
	public BCD sub(BCD bcd2){
		static final int MASK = 16;
		BCD bcd1    = new BCD(0);
		BCD bcddiff = new BCD(0);
		int bcd1ipos, bcd2ipos;
		int i, borrow = 0, tempdiff;
		
		bcd1     = this.copy();
		
	//-ve BCD number is represented by setting nybble of MSD in BCD to all 1's
	
		if ( bcd1.lessthan(bcd2) ){
			bcddiff.setNthNybble(0, 15);
			return bcddiff;
		}	
		for( i = NO_OF_NYBBLES - 1; i >= 0; i-- ){	
			bcd1ipos = bcd1.getNthNybble(i);
			bcd2ipos = bcd2.getNthNybble(i);
		
	/*If minuend digit < subtrahend digit, borrow 1 from next higher BCD digit
	  and subtract 6 from result*/
	  
			if ( bcd1ipos >= (bcd2ipos + borrow) ){
				tempdiff = bcd1ipos - bcd2ipos - borrow;
				borrow = 0;
			}	
			else{
				bcd1ipos = bcd1ipos | MASK;
				tempdiff = bcd1ipos - bcd2ipos - 6 - borrow;
				borrow = 1;
			}	
			bcddiff.setNthNybble(i, tempdiff);
		}	
		return bcddiff;
	}
	// Multiply 2 BCD nos and return their product
	
	public BCD mul(BCD bcd2){
		BCD bcdprod = new BCD(0);
		BCD bcd1    = new BCD(0);
		int i1, i2, index;
		bcd1 = this.copy();
		
		i1 = bcd1.toInteger();
		i2 = bcd2.toInteger();
	/* Adding multiplicand to itself multiplier number of times 	
	   Simple logic but inefficient due to large number of method calls */
		if ( i1 < i2 )
			for( index = 0; index < i1; index++ )
				bcdprod = bcdprod.add(bcd2);
		else
			for( index = 0; index < i2; index++ )
				bcdprod = bcdprod.add(bcd1);
		
		return bcdprod;
	}
	
	
	// Divide 2 BCD nos and return their quotient
	
	public BCD div(BCD bcd2){
		BCD bcddiv  = new BCD(this);
		BCD bcdquot;
		int plicand, quot = -1; 
	/* Subtracting dividend by divisor till convergence 	
	   Simple logic but inefficient due to large number of method calls */
		do{
			quot++;
			bcddiv = bcddiv.sub(bcd2);
			plicand = bcddiv.toInteger();
		}while ( plicand >= 0);
	
		bcdquot = new BCD(quot);
		return bcdquot;
	}
	// Divide 2 BCD nos and return the remainder
	
	public BCD mod(BCD bcd2){
		BCD bcdrem  = new BCD(this);
		int plicand; 
	/* Subtracting dividend by divisor till convergence 	
	   Simple logic but inefficient due to large number of method calls */
		do{
			if ( bcdrem.lessthan(bcd2) )
				return bcdrem;
				
			bcdrem = bcdrem.sub(bcd2);
			plicand = bcdrem.toInteger();
		}while ( plicand >= 0);
	
		return bcdrem;
	}
	
	
	//Return true if this BCD < bcd2 and false otherwise
	
	public boolean lessthan(BCD bcd2){
		int i, bcd2ipos;
		
		for(i = 0; i < NO_OF_NYBBLES; i++){
			bcd2ipos = bcd2.getNthNybble(i);
			if ( nybble[i] < bcd2ipos )
				return true;
			else if ( nybble[i] > bcd2ipos )
				return false;
		}
		return false;
	}
	//Return true if this BCD > bcd2 and false otherwise
	
	public boolean greaterthan(BCD bcd2){
		int i, bcd2ipos;
		
		for(i = 0; i < NO_OF_NYBBLES; i++){
			bcd2ipos = bcd2.getNthNybble(i);
			if ( nybble[i] > bcd2ipos )
				return true;
			else if ( nybble[i] < bcd2ipos )
				return false;
		}
		return false;
	}
	//Return true if this BCD equals bcd2 and false otherwise
	
	public boolean equalto(BCD bcd2){
		int i, bcd2ipos;
		
		for(i = 0; i < NO_OF_NYBBLES; i++){
			bcd2ipos = bcd2.getNthNybble(i);
			if ( nybble[i] != bcd2ipos )
				return false;
		}
		return true;
	}
}

***********************************************************************************************
problem -> 
2. Write a class Convert with static methods as follows: 
													a) takes 4  arguments representing miles, yards, feet and inches and converts them into
       kilometers, meters and centimeters. 
													b) takes an argument representing degrees Farenheit and converts it to degrees centrigrade. 
													c) a kilobyte is interpreted in two ways: some times it is 1000 bytes (actually correct), but
       often (and traditionally) it is 210 which is 1024. Similar discrepancies arise for mega,
       giga, tera and peta (each is 1000 (or 210 ) times the previous one). The function should
       take the 103 (standard kilo) and give the equivalent value using  210 as a kilo for all the
       above. 
       					
											[10]
Solution ->
public class Convert{
//Convert from miles, yards, feet and inches to km, meters and cm
	public static Metric fpstometric(int m, int y, int f, double i){
		final int INCHES_PER_FEET = 12;
		final int INCHES_PER_YARD = 3 * INCHES_PER_FEET;
		final int INCHES_PER_MILE = 1760* INCHES_PER_YARD;
		final double CMS_PER_INCH = 2.54;
		final int CMS_PER_METER   = 100;
		final int CMS_PER_KM      = 1000 * CMS_PER_METER;
		
		Metric metric = new Metric();
		double    totinches = 0;
		double totcm = 0;
		int km, mt;
		
	//Converting input arguements into a single unit - inches	
		totinches = m * INCHES_PER_MILE + y * INCHES_PER_YARD + f * INCHES_PER_FEET + i;
		
		totcm     = totinches * CMS_PER_INCH;
		if ( (int)totcm >  CMS_PER_KM ){
			//Set Km
			km = (int) totcm / CMS_PER_KM;
			metric.setKm(km);
			totcm = (int) totcm % CMS_PER_KM;
		}
		
		if ( (int)totcm > CMS_PER_METER ){
			//Set meters
			mt = (int)totcm / CMS_PER_METER;
			metric.setMt(mt);
			totcm = (int) totcm % CMS_PER_METER;
		}
		
		metric.setCm(totcm);
		return metric;
	}
	
	//Convert temperature in fahren-heit to degree celsius
	
	public static double fahren_to_centi(double f){
		double centi = 0.0;
		centi = 5.0 * (f - 32.0) / 9.0;
		return centi;
	}
	
	
	//Given an input in Standard Kilo units, converts it into traditional kilo units
	
	public static double std_to_trad_kilo(double stdval, char wt){
		final double STDKILO			= 1.0E3;
		final double STDMEGA			= 1.0E3 * STDKILO;
		final double STDGIGA			= 1.0E3 * STDMEGA;
		final double STDTERA			= 1.0E3 * STDGIGA;
		final double STDPETA			= 1.0E3 * STDTERA;
		
		final double STDKILO_PER_TRADKILO	= 1.024E3;
		final double STDMEGA_PER_TRADMEGA	= 1.024E3 * STDKILO_PER_TRADKILO;
		final double STDGIGA_PER_TRADGIGA	= 1.024E3 * STDMEGA_PER_TRADMEGA;
		final double STDTERA_PER_TRADTERA	= 1.024E3 * STDGIGA_PER_TRADGIGA;
		final double STDPETA_PER_TRADPETA	= 1.024E3 * STDTERA_PER_TRADTERA;
		double tradval = 0.0;
		switch(wt){
			case 'k' : case 'K' :
						tradval = (stdval / STDKILO_PER_TRADKILO) * STDKILO;
						break;
			case 'm' : case 'M' :
						tradval = (stdval / STDMEGA_PER_TRADMEGA) * STDMEGA;
						break;
			case 'g' : case 'G' :
						tradval = (stdval / STDGIGA_PER_TRADGIGA) * STDGIGA;
						break;
			case 't' : case 'T' :
						tradval = (stdval / STDTERA_PER_TRADTERA) * STDTERA;
						break;
			case 'p' : case 'P' :
						tradval = (stdval / STDPETA_PER_TRADPETA) * STDPETA;
						break;
			default:
						System.out.println("Error:Unknown weight type(Use k-kilo, m-mega, g-giga, t-tera, p-peta)");
						break;
		}				
		return tradval;
	}
/*
	public static void main(String args[]){
		Metric m = new Metric();
		double centi, val;
		
		m = fpstometric(4, 3, 8, 12.0);
		System.out.println("Km = " + m.getKm() + "\tMt = " + m.getMt() +"\tCm = " + 					m.getCm());
		
		centi = fahren_to_centi(104);
		System.out.println(104 + " degree Fahr = " + centi + " degree Celsius");
		
		val = std_to_trad_kilo(102434784, 'p');
		System.out.println("102434784 std peta= " + val + " trad units");
	}	
*/
}
											
public class Metric{
	
	private int	kilometers;
	private int	meters;
	private double  centimeters;
	public Metric(){
		kilometers  = 0;
		meters      = 0;
		centimeters = 0.0;
	}
	public Metric(int cm){
		kilometers  = 0;
		meters      = 0;
		centimeters = cm;
	}
	
	public Metric(int cm, int mt){
		kilometers  = 0;
		meters      = mt;
		centimeters = cm;
	}
	public Metric(double cm, int mt, int km){
		kilometers  = km;
		meters      = mt;
		centimeters = cm;
	}
	public double getCm(){
		return centimeters;
	}
	
	public void setCm(double cm){
		centimeters = cm;
	}
	
	public int getMt(){
		return meters;
	}
	
	public void setMt(int mt){
		meters = mt;
	}
	
	public int getKm(){
		return kilometers;
	}
	
	public void setKm(int km){
		kilometers = km;
	}
}