자바의 정석 기초(3) : 연산자 편

NtoZ·2023년 2월 22일
0

Java

목록 보기
11/23
post-thumbnail

자바의 정석 기초편 - 연산자

  • 95p~96p

3-2. 연산의 결과를 적으시오.


3-3. 십의자리 이하 버림.

  • Q : 아래는 변수 num의 값 중에서 십의 자리 이하를 버리는 코드이다. 만일 변수 num의 값이 '456'이라면 '400'이 되고, '111'이라면 '100'이 된다. (1)에 알맞은 코드를 넣으시오.
	int num = 456;
    System.out.println( (1) );
  • 처음 내 풀이과정 : num을 100으로 나누면 4.56이 된다. 4.56을 Math 클래스를 이용하여 소수점 첫째자리부터 버릴 수 있는지 생각했다. API를 찾아보니 그런 메소드는 없었다. (없는 이유가 있었다.)
  • 두번째 내 풀이과정 : String.charAt(0)메소드를 이용할 수 있을 것 같았다. num/100은 4.56이므로(틀린 지점1), 해당 값(숫자)에 빈문자열""를 더해주면 "4.56"이 된다고 생각했다. 이 때 charAt(0)을 사용해 첫 번째 자리를 문자 타입으로 반환한다. 문자 - '0'은 다시 숫자가 되므로 여기서 *100을 하면 될 것 같았다.(보충지점2)
	int num = 456;
    System.out.println( (1) );
    (1) ➡️ 
    1. num / 100
    2. (num/100)+ "" //빈문자열 더해서 문자열로 만들어주기
    3. ((num/100)+ "").charAt(0) // 그 중 첫번째 문자 가져오기
    4. ((num/100)+ "").charAt(0) - '0' // 문자 '4'라면 숫자 '4'가 된다.
    5. (((num/100)+ "").charAt(0) - '0')*100 // 숫자4 * 100은 400이다.
  • 모범답안 : 나눗셈 연산자(/)가 나머지를 버리는 점을 이용한다. 나눗셈 연산자는 나머지를 버리고 몫만 챙기므로 num/100을 통해 몫을 구해주고 다시 *100하면 십의자리 이하는 자연스레 버려진다.
	int num = 456;
	System.out.println(num/100*100);	//400
  • 내 풀이과정의 오류 :
    - 틀린 지점1 : 피연산자 두 개가 모두 int 이므로 연산값은 int가 나온다. 4.56은 double 타입으로 나올 수 없는 타입이다. 게다가 애당초 나눗셈은 몫만 반환한다.
    - 보충지점2 : 애당초 십의자리 이하만 버려지는 것이 아니다. 가장 앞자리만 숫자로 변환한 후 *100을 할 뿐이다. 예를 들어 num이 2453이라치면 453은 버려지고 retrun값이 200이 남는다.
  • 잘한 것:
    - 기본형 타입 간 전환하는 방법에 대해 잘 기억하고 있었다.
  • 반성할 것:
    - 기본적인 지식에 오개념이 생기지 않도록 주의하자.
    - 결과로 예상되지 않는 다른 값이 나오지 않는지 철저히 테스트한다.

3-4. 필요한 바구니 개수 구하기.

  • Q. 사과를 담는데 필요한 바구니(버켓)의 수를 구하는 코드. 만일 사과의 수가 123개이고 하나의 바구니에는 10개의 사과를 담을 수 있다면, 13개의 바구니가 필요할 것이다. (1)에 알맞은 코드를 넣어라.
	int numOfApples = 123; //사과의 개수
    int sizeOfBucket = 10; //바구니의 크기(바구니에 담을 수 있는 사과의 개수)
    int numOfBucket ( (1) );
    
    System.out.println("필요한 바구니의 수 :" +numOfBucket);
  • 내 풀이과정 : 간단히 사과의 개수/바구니 사이즈 +1하면 될 것이라 생각했다. 그러나 곧 나머지가 0일 경우 불필요한 바구니 하나가 남게 된다는 사실을 깨달았다. 삼항 연산자를 사용하여 나머지가 0일 경우에는 numOfApples/sizeOfBucket을 반환하고, 그 이외의 경우에는 numOfApples/sizeOfBucket+1을 반환하는 것을 생각해보았다.

  • 모범답안 : 결과값으로 numOfApples/sizeOfBucket을 반환하되, 여기에 더해서 나머지가 0이면 0을 더하고 나머지가 있으면 1을 더하는 코드

// 사과를 담는데 필요한 바구니(버켓)수 구하기
				// 사과의 수가 123개이고 하나의 바구니에는 10개의 사과만 담을 수 있다면 13개의 바구니가 필요할 것이다.
				
				int numOfApples = 123;
				int sizeOfBucket = 10;
				int numOfBucket1 = numOfApples/sizeOfBucket+1; // X 이렇게 하면 나머지가 0일 때는 오히려 불필요한 바구니가 생긴다.
				
				// 조건연산자를 활용하여 사과의 개수를 바구니로 나눈 나머지가 0이면 그 몫을, 0이 아니면 그 몫에서 1 더한 값을 반환하여 numOfBucket2에 저장.
				int numOfBucket2 = (numOfApples%sizeOfBucket==0)?numOfApples/sizeOfBucket:numOfApples/sizeOfBucket+1 ;
				
				// 모번답안 (더 간결하게 표현)
				int numOfBucket3 = numOfApples/sizeOfBucket + ((numOfApples%sizeOfBucket==0)? 0: 1);
				
				System.out.println("필요한 바구니의 수 :" +numOfBucket2);		//필요한 바구니의 수 :13
				System.out.println("필요한 바구니의 수 :" +numOfBucket3);		//필요한 바구니의 수 :13
  • 잘못한 것 : 너무 쉽게 생각한 것. 결과로 예상못한 다른 값이 나오는지 체크해보아야 한다. 또한, 코드를 보기 좋게 깔끔하게 리뷰하는 것도 필요하다.

  • 잘한 것 : 올바른 풀이과정을 생각하고 풀이를 수정한 것.


3-5. 변수 num의 값에 따라 '양수', '음수', 0을 출력하는 코드

  • Q. 변수 num의 값에 따라 '양수', '음수', 0을 출력하는 코드 작성
  • 모범 답안 : 삼항연산자 두 번 사용
		// Q. 변수 num의 값에 따라 '양수', '음수', 0을 출력하는 코드
			int num = -23;
			System.out.println((num>0)?"양수":((num<0)? "음수" : "0" ));
  • 잘한 것 : 문제의 맥락 파악, 모범답안과 정확히 일치

3-6. 화씨(Fahrenheit)를 섭씨(Celcius)로 변환하는 코드

  • Q. 화씨(Fahrenheit)를 섭씨(Celcius)로 변환하는 코드 작성. 변환 공식이 'C = 5/9 * (F -32)'라고 할 때 (1)에 알맞은 코드를 넣으시오. 단, 변환 결과값은 소수점 셋째자리에서 반올림해야 한다. (Math.round()를 사용하지 않고 처리할 것)
			int fahrenheit = 100;
			float celcius = /*(1)*/;
			
			System.out.println("Fahrenheit:"+fahrenheit);
			System.out.println("Celcius:"+celcius);
  • 나의 풀이과정:
/*
			 * **Q.** 화씨(Fahrenheit)를 섭씨(Celcius)로 변환하는 코드 작성. 
			 * 변환 공식이 'C = 5/9 * (F -32)'라고 할 때 (1)에 알맞은 코드를 넣으시오. 
			 * 단, 변환 결과값은 소수점 셋째자리에서 반올림해야 한다. (Math.round()를 사용하지 않고 처리할 것)
			 */

			int fahrenheit = 100;
							//9.0f로 나누지 않고 int 9로 나누면 나머지가 버려진다.
			float celcius = (5/9.0f)*(fahrenheit-32);
			System.out.println("Celcius:"+celcius); //37.77778
			//계산은 잘 되었다. 소수점 셋째자리에서 반올림을 어떻게 할 것인가?
			//Math.round()를 사용하는 경우 Math.round(변수*100)을 다시 100.0f(!!실수로 나눠야함을 주의)으로 나누면 된다.
			//celcius = (Math.round(celcius*100))/100.0f;
		
			//그러나 Math.round()를 사용하지 않는 경우,
			//*1000을 해서 소수점 세째자리까지 포함하는 정수를 만든다?
			/*
			 * 아이디어 : *1000을 해서 나머지를 버린 정수(int a), 
			 * 			*100을 해서 나머지를 버리고 다시 *10을 해서 일의자리 수를 0으로 만든 같은자리수 정수(int b)랑 비교해서 
			 * 			그 차이가 5 이상이면 b에 10을 더한 뒤 다시 1000으로 나누면 (, 바보야 1000.0f로 나눠야지..)
			 * 			원래 celcius에서 소숫점 셋째자리에서 반올림한 수가 되지 않을까?
			 *) ( 37777(a) - 37770(b) >= 5 ) ? b + 10 : b 
			 * 아이디어 실현 문제점 : celcius의 타입이 float이기 때문에 int로 곱해도 나머지가 버려지지 않는다. (자동형변환)
			 * 			=> 그럼 강제 형변환 해보면 어때? 어차피 온도라 overflow가 발생하지 않네!
							 */
			int a = (int)((5/9.0f)*(fahrenheit-32)*1000);	// a = 37777
			int b = ((int)((5/9.0f)*(fahrenheit-32)*100))*10;	// b = 37770
			System.out.println("a:" + a); //a:37777
			System.out.println("b:" + b); //b:37770
			celcius = ((a-b>=5)? b+10:b)/1000.0f;	// 37.78 (Math.round()없이 소수점 셋째자리에서 반올림완료)
				  
			System.out.println("Fahrenheit:"+fahrenheit);
			System.out.println("Celcius:"+celcius);	
  • 잘한 점 : 목표(goal)을 달성했다. 강제 형변환이라는 아이디어를 생각해서 아이디어 실현 과정에서 생긴 문제점을 극복했다.

  • 아쉬운 점 : (1) 안에 간략하게 들어갈 수 있는 방법을 생각하지 못했다. 풀이과정이 비효율적인 것 같다.

  • 모범 답안 :

	celcius = ((int)((5/9.0f)*(fahrenheit-32)*100 + 0.5f) / 100f);
	System.out.println("Fahrenheit:"+fahrenheit);	// Fahrenheit:100
	System.out.println("Celcius:"+celcius);	//	Celcius:37.78
  • 모범 풀이 :
    1. (5/9.0f)*(fahrenheit-32)는 float 리터럴로 37.77778f를 갖는다.
    2. 해당 값에서 100을 곱하면 3777.778f이다.
    3. 0.5f를 더하면 3778.278f이다.
    4. (int) 강제 형변환으로 3778을 제외한 나머지를 버린다.
    5. 나누기 100을 통해 원 자리수로 맞춰 준다.
    6. 37.78이 된다.

  • 내가 생각 못했던 것: 0.5f를 더하고나서 int로 형변환 하는 것.
    - 생각해보니 소수점 셋째자리 쪽에서 5를 더하면 소수점 셋째자리가 5이상일 경우 무조건 1 올림이 발생한다. 어차피 int로 소수점 셋째자리부터는 지워주면 되는 것이다!
profile
9에서 0으로, 백엔드 개발블로그

0개의 댓글