우리는 Intro to Programming에서 두 개의 정수를 나누면 항상 정수를 얻는다는 것을 배웠습니다. 문제를 해결하려면이 정수 중 하나 이상을 실수로 만드십시오.
왜 컴파일러가 결과가 10 진수가되기를 바라는지 이해하지 못합니까?
설명
답변
왜 컴파일러가 결과가 10 진수가되기를 원하는지 이해하지 못합니까?
C ++ 컴파일러는 C ++ 표준에 명시된대로 잘 정의되고 결정적인 규칙 을 따르고 있습니다. C ++ 표준에는 이러한 규칙이 있습니다. 0a061937c1 “>
표준위원회 는 그렇게하기로 결정했습니다.
그들은 정수 수학 결과가 부동 소수점 숫자가된다고 말하는 표준을 작성했거나 나머지의 경우입니다. 그러나 복잡성이 더해집니다. 결과가 무엇인지 미리 알아야하거나 항상 부동 소수점을 제공하는 경우 정수로 다시 변환해야합니다. 아마도 정수를 원 합니다. .
C ++의 핵심 철학 중 하나는 “사용하지 않는 것에 대해 비용을 지불하지 않습니다. . ” 실제로 정수와 부동 소수점을 혼합하는 복잡성을 원 하고 (추가 CPU 명령 및 메모리 액세스에 수반되는 1 ) 질문에서 언급 한대로 유형 캐스트를 수행합니다. . 그렇지 않으면 표준 정수 수학을 고수하십시오.
마지막으로 정수와 부동 소수점 변수를 혼합하면 아래에서 설명하는 것처럼 정밀도가 떨어지고 때로는 잘못된 결과가 발생할 수 있습니다. 원하는 경우 비용을 지불하십시오. 그렇지 않으면 표준에 따라 컴파일러가 데이터 유형을 혼합하기위한 엄격한 규칙 세트를 고수해야합니다. 이것은 잘 정의 된 동작입니다. C ++ 개발자로서 저는 이것을 표준에서 찾아보고 어떻게 작동하는지 볼 수 있습니다.
기본적으로 수행하려는 작업을 수행하는 세 가지 방법이 있습니다. 각각 장점과 단점이 있습니다.
-
정수 수학 :이 결과는 나눗셈 중에 결과가 잘립니다. 소수 부분을 원하는 경우 나눈 나머지를 구하고 소수 부분을 나머지 부분을 제수로 나눈 값으로 처리하여 별도로 처리해야합니다. 이것은 작업이 좀 더 복잡하고 조작 할 변수가 더 많습니다.
-
부동 소수점 수학 : 일반적으로 작은 값에 대해 올바른 (충분한) 결과를 생성하지만 특히 지수가 증가함에 따라 정밀도와 반올림으로 오류를 쉽게 도입 할 수 있습니다. 큰 숫자를 작은 숫자로 나누면 숫자의 스케일이 서로 잘 어울리지 않아 언더 플로가 발생하거나 잘못된 결과를 얻을 수도 있습니다.
-
자신의 수학을하십시오. 십진수 및 유리수의 확장 정밀도 를 처리하는 클래스가 있습니다. 이들은 일반적으로 내장 유형의 수학보다 느리지 만 일반적으로 여전히 매우 빠르며 임의 정밀도 수학을 제공합니다. 반올림 및 기타 문제는 IEEE 플로트와 같이 자동으로 수행되지 않지만 더 많은 제어와 확실히 더 정확한 정확도를 얻을 수 있습니다.
여기서 핵심은 문제 영역에 따라 선택하는 것입니다. . 숫자를 나타내는 세 가지 방법 모두 고유 한 장점과 단점이 있습니다. 루프 카운터를 사용하십니까? 통합 유형을 선택하십시오. 3D 공간에서 위치를 나타내는가? 아마도 수레 그룹 일 것입니다. 돈을 추적하고 싶습니까? 고정 소수점 유형을 사용합니다.
1 가장 많이 사용되는 CPU 아키텍처 (예 : x86-64 ) )에는 정수 및 부동 소수점과 같은 서로 다른 레지스터 유형에서 작동하는 별도의 명령어 세트와 함께 정수, 부동 소수점 및 이들의 다양한 표현 (부호 없음 및 부호 없음, 부동 및 이중)간에 변환하는 추가 명령어가 있습니다. 이러한 작업 중 일부는 메모리 액세스도 수반 할 수 있습니다. 값을 변환하여 메모리 (해당 변수)에 저장합니다. CPU 수준의 수학은 “integer in, float out”만큼 간단하지 않습니다.”두 개의 정수를 추가하는 것은 매우 간단한 작업 일 수 있지만 단일 명령어 일 수 있지만 데이터 유형을 혼합하면 복잡성이 증가 할 수 있습니다.
댓글
- C ++ 표준이 그렇게되어야한다고 규정하고 있습니다. 그 이유는 무엇입니까? ' 말하기가 더 쉬워지지 않을까요? " 균등하게 나눌 수없는 정수의 나눗셈은 부동 수로, 다른 나눗셈은 공정한 게임입니다. "
- @ moonman239 내 수정 사항보기
- @ moonman239 컴파일러 작성자 용이 아닙니다. 일반적으로 사용되는 많은 CPU 아키텍처는 두 개의 정수로 나누기를 요청하면 정수 결과를 제공합니다. 정수가 아닌 결과를 확인한 다음 더 느린 부동 소수점을 사용하도록 전환해야합니다. 또는 부동 소수점 나누기로 기본 설정되어 빠른 수학을 원하는 사람들, 정확한 수학을 원하는 사람들, C에 익숙한 사람들의 관심을 잃었을 수 있습니다. 은 ' 기존 코드와의 호환성을 손상시킬 수 있으므로 옵션이 아닙니다.
- 이를 대안으로 옹호하는 것이 아니라 정적 유형의 표현식을 만듭니다. C ++ '의 정적 유형 시스템에서 작동하지 않는 ' 피연산자의 런타임 값에 따라 다릅니다.
- @ moonman239 : 피연산자의 값 에 따라 다른 유형을 생성하는 연산을한다는 것은 엄청난 일입니다.
답변
이것은 하드웨어의 진화 때문입니다. 컴퓨터 초창기에는 모든 기계가 부동 소수점 단위를 가지고있는 것은 아니었고, 하드웨어는 단순히 부동 소수점 수의 개념을 이해할 수 없었습니다. 물론 부동 소수점 숫자는 소프트웨어 추상화로 구현 될 수 있지만 상당한 단점이 있습니다. 이러한 시스템의 모든 산술은 기본적으로 순수 정수 산술이어야했습니다.
현재도 CPU 내에서 정수와 부동 소수점 산술 단위 사이에는 확고한 차이가 있습니다. 피연산자는 시작하기 위해 별도의 레지스터 파일에 저장되고 정수 단위는 두 개의 정수 인수를 취하고 정수 레지스터로 끝나는 정수 결과를 생성하도록 연결됩니다. 일부 CPU에서는 정수 값을 메모리에 저장 한 다음 부동 소수점 레지스터로 다시로드해야 부동 소수점 숫자로 다시 코딩 할 수 있으므로 부동 소수점 분할을 수행 할 수 있습니다.
그러므로 언어 초기에 C 개발자가 내린 결정 (C ++은 단순히이 동작을 상속 함)은 유일하게 적절한 결정이었으며 오늘날에도 여전히 가치가 있습니다. 부동 소수점 수학이 필요한 경우 그것을 사용할 수 있습니다. 필요하지 않다면 그럴 필요가 없습니다.
댓글
- C ++ 표준의 생성은 오늘날 꽤 쓸모가 없습니다! 예 : " 사용하지 않는 것에 대해서는 비용을 지불하지 않습니다. " 오늘날 하드웨어는 당연한 것으로 간주되고 모든 사용자가 원하는 것은 실행!
- @ mahen23 모든 사용자가 이렇게 생각하는 것은 아닙니다. 저는 프로그램이 수천 개의 CPU 코어에서 병렬로 실행되는 분야에서 일합니다. 이 영역에서 효율성은 투자 및 순수 전력 소비 측면에서 모두 돈입니다. Java와 같은 언어는 해당 영역에서 기회의 유령이 아닙니다.
- @ mahen23 아니요. ' t-이상입니다. 데스크톱 이상의 현재 CPU 아키텍처를 살펴 보는 경우에만 해당됩니다. 여전히 부동 소수점 연산을 지원하지 않거나 부분적으로 만 지원하는 ' 많은 임베디드 시스템이 있으며, C 및 C ++는 부동 소수점 연산을 최대한 효율적으로 구현하기 위해 계속해서 지원합니다. 어셈블러를 사용하여. BTW, Python과 같은 더 높은 수준의 언어는 정수와 FP 연산을 구분합니다.
10 / 3
를 사용해보세요.
Answer
10/2 정수를 사용하면 정확히 5-정답입니다.
부동 소수점 수학을 사용하면 10/2 할 수 있습니다 . 대답 *.
즉, 현재 하드웨어에서 부동 소수점 숫자가 “완벽”하다는 것은 불가능합니다. 정수 수학 만 정확할 수 있습니다. 불행히도 소수점 자리는 할 수 없지만 쉬운 작업이 있습니다. 예를 들어 4/3 대신에 (4 * 1000) / (3 * 1000) == 1333을 수행합니다. 사용자에게 답을 표시 할 때 소프트웨어에서.를 그립니다 (1.333). 이렇게하면 소수점 이하 자릿수로 인해 틀린 답이 아닌 정확한 답을 얻을 수 있습니다.
부동 소수점 수학 오류가 합쳐져 심각한 오류가 발생할 수 있습니다. 금융과 같은 중요한 것은 정수 수학을 사용합니다. .
* 10 / 2 예제는 실제로 부동 소수점 수학에서 정확합니다. 하지만 믿을 수는 없습니다. 다른 많은 숫자가 잘못된 결과를 제공합니다.자세한 내용은 다음을 참조하십시오. http://http.cs.berkeley.edu/~wkahan/ieee754status/ieee754.ps 요점은 부동 소수점이있을 때마다 정확도에 의존 할 수 없다는 것입니다. 관련
코멘트
- IEEE 754 호환 부동 소수점 구현은 10/2에 대한 정확한 결과를 제공합니다. 실제로 정확한 정수 결과가있는 정수 피연산자 만 포함하는 모든 연산에 대한 결과는 피연산자와 결과를 정확하게 표현할 수있는 경우 “충분히 작은”정수로 표현할 수 있습니다.
- @ 5gon12eder there ' s nit pick을 사용할 필요가 없습니다. 저는 ' 단순한 용어로 복잡한 문제를 설명하려고합니다. 정수가 아닌 값을 지원하는 요점은 소수점 이하 자릿수 ( 모든 것을 원하는 소수 자릿수로 간단히 곱하여 정수를 사용하여 수행 할 수 있습니다.
Answer
기술적으로 완전히 정확하지는 않지만 C ++는 여전히 C의 상위 집합으로 간주되며, 그로부터 영감을 받아 일부 속성, 정수 분할이 그중 하나입니다.
C는 대부분 효율적이고 빠르도록 설계되었으며 정수는 일반적으로 정수 유형은 하드웨어에 연결되어있는 반면 부동 소수점은 계산해야하기 때문에 부동 소수점보다 훨씬 빠릅니다.
/
피연산자가 두 개의 정수를 받으면 하나 왼쪽의 피연산자가 왼쪽의 피연산자에 몇 번 들어가는 지 묻는 간단한 덧셈과 루프를 사용하여 결과를 계산할 수 있습니다.
//
는 정수 나누기 연산자이고#
는 한 줄 주석입니다. 파스칼에서 정수 나누기 연산자는 키워드div
. 둘 다 해당 언어에서 매우 잘 작동합니다. ges. C는 아마도 가능한 최악의 일을합니다. 하나의 연산자는 임의의 컨텍스트에 따라 완전히 다른 두 가지 일을 할 수 있습니다.