[개발팁]SICP 문제 입니다. 0 2 4,211

by 허용운 [JAVA 관련] 개발팁 자바 java interface 인터페이스 제네릭 [2009.01.13 10:48:12]


아래 코드는 SICP 1.29 의 연습문제를 누군가 자바로 풀어 놓은 내용 입니다.
참조경로 를 보시면 나온 내용인데. 원래 innerClass 를 이용한 Build패턴을
구현하다가 찾게된 코드인데... 인터페이스를 이용한 코드의 처리가 거의 아트의
수준 입니다. 코드를 읽다가 보면 정말 중복도 없고 군더더기도 없습니다.
관련 문제를 해결하기 위해서 처음에 문제 풀기를 시도한 사람은 제네릭을 이용한
처리로 접근을 했는데 이렇게도 인터페이스를 이용할수 있다는 사실에 놀랐습니다.
한번쯤 살펴 보시기에 좋은 코드라 생각이 되어 글을 남깁니다.
 
import java.math.*;

public class Test {
interface Function {
public Number invoke(Number a);
}

public static Number sum(Function term, Number a, Function next, Number b) {
if(compare(a, b)>0) return (ensureType(0, a)[0]);
else return add(term.invoke(a), sum(term, next.invoke(a), next, b));
}

public static Function cube=new Function() {
public Number invoke(Number a) {
return multiply(multiply(a, a), a);
}
};

public static Function inc=new Function() {
public Number invoke(Number a) {
return add(a, 1);
}
};

public static Function identity=new Function() {
public Number invoke(Number a) {
return a;
}
};

public static Number sumCubes(Number a, Number b) {
return sum(cube, a, inc, b);
}

public static Number sumIntegers(Number a, Number b) {
return sum(identity, a, inc, b);
}

public static Number piSum(Number a, Number b) {
Function piTerm=new Function() {
public Number invoke(Number x) {
return divide(1.0, multiply(x, add(x, 2)));
}
};
Function piNext=new Function() {
public Number invoke(Number x) {
return add(x, 4);
}
};
return sum(piTerm, a, piNext, b);
}

public static Number integral(Function f, Number a, Number b, final Number dx) {
Function addDx=new Function() {
public Number invoke(Number x) {
return add(x, dx);
}
};
return multiply(sum(f, add(a, divide(dx, 2.0)), addDx, b), dx);
}

public static Number integralSimpson(final Function f, final Number a, final Number b, final Number n) {
final Number h=divide(subtract(b, a), multiply(n, 1.0));
final Function y=new Function() {
public Number invoke(Number k) {
return f.invoke(add(a, multiply(k, h)));
}
};
Function term=new Function() {
public Number invoke(Number k) {
return multiply(compare(remainder(k, 2), 0)!=0?4:2, y.invoke(k));
}
};
return multiply(divide(h, 3.0), add(add(y.invoke(0), sum(term, 1, inc, subtract(n, 1))), y.invoke(n)));
}

public static void main(String[] args) {
System.out.println(sumCubes(1, 10));
System.out.println(sumIntegers(1, 10));
System.out.println(multiply(8, piSum(1, 1000)));
System.out.println(integral(cube, 0, 1, 0.01));
System.out.println(integral(cube, 0, 1, 0.001));
System.out.println(integralSimpson(cube, 0, 1, 100));
System.out.println(integralSimpson(cube, 0, 1, 1000));
}

// 이하 부분은 java 언어가 연산자 오버로딩을 지원하지 않기 때문에 추가합니다
public static Number[] ensureType(Number a, Number b) {
Number[] ret;
if(a instanceof BigDecimal&&b instanceof BigDecimal) {
ret=new BigDecimal[2];
ret[0]=a; ret[1]=b;
} else if(a instanceof BigDecimal) {
ret=new BigDecimal[2];
ret[0]=a; ret[1]=new BigDecimal(b.toString());
} else if(b instanceof BigDecimal) {
ret=new BigDecimal[2];
ret[0]=new BigDecimal(a.toString()); ret[1]=b;
} else if(a instanceof Double&&b instanceof BigInteger||a instanceof BigInteger&&b instanceof Double) {
ret=new BigDecimal[2];
ret[0]=new BigDecimal(a.toString()); ret[1]=new BigDecimal(b.toString());
} else if(a instanceof BigInteger&&b instanceof BigInteger) {
ret=new BigInteger[2];
ret[0]=a; ret[1]=b;
} else if(a instanceof BigInteger) {
ret=new BigInteger[2];
ret[0]=a; ret[1]=new BigInteger(b.toString());
} else if(b instanceof BigInteger) {
ret=new BigInteger[2];
ret[0]=new BigInteger(a.toString()); ret[1]=b;
} else if(a instanceof Double||b instanceof Double) {
ret=new Double[2];
ret[0]=a.doubleValue(); ret[1]=b.doubleValue();
} else if(a instanceof Float||b instanceof Float) {
ret=new Float[2];
ret[0]=a.floatValue(); ret[1]=b.floatValue();
} else if(a instanceof Long||b instanceof Long) {
ret=new Long[2];
ret[0]=a.longValue(); ret[1]=b.longValue();
} else {
ret=new Integer[2];
ret[0]=a.intValue(); ret[1]=b.intValue();
}
return ret;
}

public static Number add(Number a, Number b) {
Number[] v=ensureType(a, b);
if(v instanceof BigDecimal[]) {
BigDecimal[] w=(BigDecimal[])v;
return (w[0].add(w[1]));
} else if(v instanceof BigInteger[]) {
BigInteger[] w=(BigInteger[])v;
return (w[0].add(w[1]));
} else if(v instanceof Double[]) {
Double[] w=(Double[])v;
return (w[0]+w[1]);
} else if(v instanceof Float[]) {
Float[] w=(Float[])v;
return (w[0]+w[1]);
} else if(v instanceof Long[]) {
Long[] w=(Long[])v;
return (w[0]+w[1]);
} else {
Integer[] w=(Integer[])v;
return (w[0]+w[1]);
}
}

public static Number subtract(Number a, Number b) {
Number[] v=ensureType(a, b);
if(v instanceof BigDecimal[]) {
BigDecimal[] w=(BigDecimal[])v;
return (w[0].subtract(w[1]));
} else if(v instanceof BigInteger[]) {
BigInteger[] w=(BigInteger[])v;
return (w[0].subtract(w[1]));
} else if(v instanceof Double[]) {
Double[] w=(Double[])v;
return (w[0]-w[1]);
} else if(v instanceof Float[]) {
Float[] w=(Float[])v;
return (w[0]-w[1]);
} else if(v instanceof Long[]) {
Long[] w=(Long[])v;
return (w[0]-w[1]);
} else {
Integer[] w=(Integer[])v;
return (w[0]-w[1]);
}
}


public static Number multiply(Number a, Number b) {
Number[] v=ensureType(a, b);
if(v instanceof BigDecimal[]) {
BigDecimal[] w=(BigDecimal[])v;
return w[0].multiply(w[1]);
} else if(v instanceof BigInteger[]) {
BigInteger[] w=(BigInteger[])v;
return w[0].multiply(w[1]);
} else if(v instanceof Double[]) {
Double[] w=(Double[])v;
return w[0]*w[1];
} else if(v instanceof Float[]) {
Float[] w=(Float[])v;
return w[0]*w[1];
} else if(v instanceof Long[]) {
Long[] w=(Long[])v;
return w[0]*w[1];
} else {
Integer[] w=(Integer[])v;
return w[0]*w[1];
}
}

public static Number divide(Number a, Number b) {
Number[] v=ensureType(a, b);
if(v instanceof BigDecimal[]) {
BigDecimal[] w=(BigDecimal[])v;
return w[0].divide(w[1], RoundingMode.HALF_EVEN);
} else if(v instanceof BigInteger[]) {
BigInteger[] w=(BigInteger[])v;
return w[0].divide(w[1]);
} else if(v instanceof Double[]) {
Double[] w=(Double[])v;
return w[0]/w[1];
} else if(v instanceof Float[]) {
Float[] w=(Float[])v;
return w[0]/w[1];
} else if(v instanceof Long[]) {
Long[] w=(Long[])v;
return w[0]/w[1];
} else {
Integer[] w=(Integer[])v;
return w[0]/w[1];
}
}

public static Number remainder(Number a, Number b) {
Number[] v=ensureType(a, b);
if(v instanceof BigDecimal[]) {
BigDecimal[] w=(BigDecimal[])v;
return w[0].remainder(w[1]);
} else if(v instanceof BigInteger[]) {
BigInteger[] w=(BigInteger[])v;
return w[0].remainder(w[1]);
} else if(v instanceof Double[]) {
Double[] w=(Double[])v;
return w[0]%w[1];
} else if(v instanceof Float[]) {
Float[] w=(Float[])v;
return w[0]%w[1];
} else if(v instanceof Long[]) {
Long[] w=(Long[])v;
return w[0]%w[1];
} else {
Integer[] w=(Integer[])v;
return w[0]%w[1];
}
}

@SuppressWarnings("unchecked")
public static int compare(Number a, Number b) {
Number[] v=ensureType(a, b);
return ((Comparable)v[0]).compareTo((Comparable)v[1]);
}
}

by 김정식 [2009.01.13 11:11:10]
용운아 게시글 이동했어..

by 꼬비 [2014.09.25 15:01:36]

좋은 정보 감사합니다~

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입