9roomthon 구현 1일차: 운동 중독 플레이어

PEA은하·2023년 8월 14일
post-thumbnail

Problem


문제 설명

나눗셈이 포함된 수식을 계산하기 위해

  1. 정수형으로 주어진 두 숫자를 입력받고
  2. 소수점 아래 숫자까지 계산하여
  3. 그 결과를 정수형으로 출력한다.

즉, 입출력은 정수형인데 계산 과정에는 실수형이 필요한 문제이다.

필요한 명령어

PythonC++C
표준 입출력 함수var = input( )
print( var )
#include < iostream >
cin >> var;
cout << var;
#include < stdio.h >
scanf("%d", &var);
printf("%d", var);
타입 변환
(Type casting)
var = int( val )암묵적 형변환
int var = val;
명시적 형변환
(float) val;
int var = val;
(float) val;
소수점 버림
소수점 내림
import math
var = math.trunc( val )
var = math.floor( val )



Submitted Code


Python

1 W, R = map(int, input().split())
2 print(int(W * (1 + R / 30)))

Line 1

input()을 공백 기준으로 분리하고, 각각 int 자료형으로 변환하여 대입한다.

Line 2

수식 계산 결과를 int 자료형으로 변환하여 출력한다. 파이썬에서는 실수 나눗셈 연산자를 사용하면 정수 / 정수의 연산 결과도 실수로 반환*한다. R / 30의 결과가 실수이므로, 소수점 이하 숫자를 계산에 포함하게 된다.

  • 정수 / 정수 = 실수 는 버전 3.x 이후에서 가능하다. 버전 2.x에서는 정수로 반환한다.

C++

 1 #include <iostream>
 2 using namespace std;
 3
 4 int main() {
 5     int W, R;
 6     cin >> W >> R;
 7    
 8     int answer = W * (1 + (float) R / 30);
 9     cout << answer << endl;
10     return 0;
11 }

Line 1

입출력 헤더 파일을 추가한다.

Line 2

기본 네임스페이스를 std로 선언한다.

Line 5-6

W와 R에 순서대로 정수형 숫자를 대입한다. 입력값이 공백 및 NULL 문자('\0')를 기준으로 끊어 읽기 때문에 공백으로 구분된 두 숫자를 분리해서 대입할 수 있다.

Line 8

R을 float 자료형으로 변환하여 수식을 계산한다. float / int이므로 30이 암묵적 형변환 되고, 계산 결과는 float이다.

Line 9

answer를 출력하고, endl로 줄바꿈한다.


C

 1 #include <stdio.h>
 2
 3 int main() {
 4     int W, R;
 5     int answer;
 6     scanf("%d %d", &W, &R);
 7   
 8     answer = W * (1 + (float) R / 30);
 9     printf("%d", answer);
10     return 0;
11 }

Line 1

입출력 헤더 파일을 추가한다.

Line 4-5

C언어는 사용할 변수를 코드의 시작 부분에 모아서 선언한다.

Line 6

정수형 변환문자 %d를 사용하여, 공백으로 분리된 두 숫자를 W와 R의 주소에 저장한다.

Line 8

C++ 코드와 같은 이유로, R을 float 자료형으로 변환하여 수식을 계산한다.

Line 9

answer의 값을 정수형으로 출력한다.

입출력


프로그래밍 언어의 종류와 관계없이 입출력 데이터의 자료형은 모두 문자(char)이다. 이는 파이썬과 자바의 입출력 함수에서 잘 드러난다.

Python

input() 함수의 자료형이 str이고, 출력할 때도 "문자열"을 사용하는 것을 볼 수 있다.

value = input()
print(f"사용자의 입력은 {type(value)} 타입입니다.")     
# 출력 결과: 사용자의 입력은 <class 'str'> 타입입니다.

Java

next() 함수를 사용하여 String으로 입력받고, 나머지 자료형을 입력받는 함수의 이름은 next + 자료형으로 설정되어 있다.

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
    	Scanner scanner = new Scanner();
        String text = scanner.next();            // String 입력
        int number1 = scanner.nextInt();         // int 입력
        double number2 = scanner.nextDouble();   // double 입력
        boolean bool = scanner.nextBoolean();    // boolean 입력
        scanner.close();
    }
}

(개인적인 생각이지만) 입출력 데이터의 기본 자료형이 String이므로 next라는 함수명을 사용하고, 나머지 자료형을 위한 함수에는 자료형을 명시적으로 표시한 것으로 보인다.


Python

input 함수

줄바꿈('\n') 문자를 기준으로 입력된다.
문제에서 두 숫자가 한 줄에 입력되므로, input 함수로 입력받은 후 공백(space) 문자를 기준으로 분리해야 한다. 또한 string object이므로, int 자료형으로 변환한다.

print 함수의 end 옵션은 기본값이 줄바꿈('\n') 문자이므로, 문자열 출력 후 자동으로 줄바꿈 된다. end=' '로 변경하면 줄바꿈 없이 다음 print 함수의 문자열을 출력할 수 있다.

파이썬은 버전 업데이트가 다른 언어에 비해 잦기 때문에, 버전별 차이점을 알아둘 필요가 있다. 버전별 출력 방법은 다음과 같다.

버전문자열
2.x괄호 없이도 사용 가능
예) print "1 + 2 = {}".format(1 + 2)
3.xformat 메서드
예) print("1 + 2 = {}".format(1 + 2))
3.8 이후f-string도 지원
예) print(f"1 + 2 = {1 + 2}")

C

scanf 함수

NULL 문자('\0')를 기준으로 입력된다.
변환문자를 활용하여 특정 위치의 문자를 변수에 대입할 수 있다. 이때 일반적인 대입과는 달리 변수의 주소(포인터)를 입력해야 한다.

// 일반적인 대입
int var = 5;

// 입력값 받기
scanf("%d", &var);

그 이유는 라이브러리 함수가 main 함수와 별도로 컴파일되면서, 컴파일러의 메모리에 저장된 주소 매핑 테이블*을 사용할 수 없기 때문이다.

  • 주소 매핑 테이블은 사용자가 지정한 변수명과 이에 할당된 프로세스 메모리의 실제 주소를 기록한 LUT이다.

printf 함수

변환문자를 활용해 문자열을 출력한다.


C++

std::cin

공백(' '), 줄바꿈('\n'), NULL 문자('\0')를 기준으로 입력된다.
문제에서 두 숫자가 공백 문자를 기준으로 입력된다. 따라서 첫 번째 문자열은 첫 번째 변수인 W에, 두 번째 문자열은 두 번째 변수인 R에 대입된다.

C언어와 달리 변수명을 입력하는 이유는 포인터가 아닌 참조자(reference)를 사용하기 때문이다.

std::cout

문자열을 출력한다.



Code Review


풀이 1: 정수 자료형만 사용하도록 수식 순서 변경

변경 전

int RM = W * (1 + R / 30);    # R / 30에서 소수점 버림이 먼저 발생해서 오답

변경 후

int RM = W + W * R / 30;      # W * R 계산 후에 소수점 버림

풀이 2: 실수 자료형 사용

double W, R;
double RM = W * (1.0 + R / 30.0);
cout << int(floor(RM));

Python

  • math.trunc() 사용

1. math.trucn() 함수

소수 부분을 버림

import math
print(math.trucn(3.14))    # 3
print(math.trucn(-3.14))   # -3

math.floor() 함수는 소수 부분을 내림

import math
print(math.floor(3.14))    # 3
print(math.floor(-3.14))   # -4

2. math.trucn vs. int

print(int(3.14))    # 3
print(int(-3.14))   # -3

math.trucn() 함수와 int() 함수는 동일한 결과를 반환한다. 다만, int() 함수는 integer로 형변환 시키기 때문에 단순 버림을 위해서는 math.trucn() 함수가 빠를 수 있다.

C++

1. float 말고 double 사용

크기정수 범위소수 범위
float32비트 범위4byte6자리(적음)
double64비트 범위8byte15자리

2. int(floor()) vs. int()

소수점 반올림이 아니라 버림이라면, int() 함수가 더 간편해 보인다. 해설에서는 floor() 함수의 타입(double)을 주의하라고 알려주기 위해서 int(floor())를 사용한 것으로 예상한다.

3. bits/stdc++.h 헤더

C++의 표준 헤더를 모두 불러오는 헤더

  • 표준 헤더가 아니므로, GCC 컴파일러를 사용하는 환경에서만 사용 가능
  • GCC 컴파일러 : (간단하게 이해한 바로는) C언어용 컴파일러



Challenge Review


1일차에 기본 입출력 구현 문제가 나왔다.
C/C++을 익히는 게 목표여서 오히려 좋아.

1. int와 float 범위 고려하기

이번 문제는 W, R 범위가 크지 않아서 바로 사용했지만, 다음 번에는 미리 생각해보자.

32bit64bit
int4byte4byte
float4byte
  • int = 4byte. (4 x 8bit = 32bit = 2의 32제곱)
  • float = 정수 4byte + 소수점 이하 6자리



Reference


0개의 댓글