2014-09-05 9 views
21
#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 

int main() 
{ 
    int n,i,ele; 
    n=5; 
    ele=pow(n,2); 
    printf("%d",ele); 
    return 0; 
} 

출력은 24입니다.컴파일러와 OS에서 n = 5 일 때 pow (n, 2)가 24를 반환하는 이유는 무엇입니까?

저는 Code :: Blocks에서 GNU/GCC를 사용하고 있습니다.

현재 무슨 일입니까?

은 내가 pow 함수가 double 반환 알고 있지만 25은 그래서 INT 타입에 맞는 왜 24 대신 25의이 코드가 인쇄합니까? n=4; n=6; n=3; n=2; 코드는 작동하지만 5는 작동하지 않습니다.

+0

'float ele;'(* 이전 코드와 같이'% f' 인쇄 형식)을 사용하십시오 - 표시되는 내용은 무엇입니까? – user2864740

+1

'float' 또는'double' 변수에서'pow'의 리턴 값을 취한 다음'int'로 타이 캐스팅 해 볼 수 있습니다. 그것이 또한'24' 또는 정답'25'을 생성하는지 확인하십시오. –

+0

@ Don'tYouWorryChild 나중에 작동하지만, int에서 리턴 값을 취할 수없는 이유는 무엇입니까? 시험에서 조교는 "예, 당신은 힘을 되찾기 위해 int를 사용할 수 있습니다"라고 말했습니다. 그래서 ... 그는 틀 렸습니다. – exsnake

답변

22

이 될 것입니다. 컴파일러의 pow 함수의 구현을 살펴보면이 사실을 확인할 수 있습니다.

정확한 #include를 가지고 있다고 가정하면 (앞의 모든 대답과 의견은 정확합니다. #include 파일을 가져 가지 마십시오.

double pow(double, double);

하고이 같은 pow 전화하는거야 :

pow(5,2);

01) 부여, 표준 pow 함수의 프로토 타입이있다

pow 함수는 (대수를 사용하여) 알고리즘을 거치므로 부동 소수점 함수 및 값을 사용하여 전력 값을 계산합니다.

pow 함수는 분수 지수를 사용하여 pow을 계산해야하기 때문에 "x의 값을 n 번 누름"을 순진하지 않습니다. 따라서 분수 지수를 계산할 수 없습니다.

아마도 매개 변수 5와 2를 사용하여 pow을 계산하면 약간의 반올림 오류가 발생합니다. int에 할당 할 때 분수 값이 잘 리므로 24를 얻을 수 있습니다.

정수를 사용하는 경우 값을 단순히 필요한 횟수만큼 곱하는 자체 "intpow"또는 유사한 함수를 작성할 수도 있습니다 .이것의 장점은 : 당신은 당신이 pow를 사용하여 미묘한 반올림 오류가 발생할 수 있습니다 상황에받지 않습니다

  1. .

  2. intpow 함수는 pow에 해당하는 함수보다 더 빠르게 실행됩니다.

+13

자신의 정수 배율을 굴릴 경우 후자가 ** O이므로 반복 곱하기보다는 [제곱에 의한 지수화] (http://en.wikipedia.org/wiki/Exponentiation_by_squaring)를 사용해야합니다. n) **이고 전자는 ** O (log n) **이다. – aruisdante

+2

@aruisdante : 표기법이 사실상 [pseudo-linear] (https://en.wikipedia.org/wiki/Pseudo-polynomial_time)에서 선형 복잡성으로 바뀔 때 선형에서 로그의 복잡성으로의 전환을 제안합니다. –

+1

@BenVoigt 기술적으로 앞의 설명은보다 구체적이어야합니다. 순진 알고리즘은 O (n) 산술 연산 (곱셈 또는 덧셈)이 필요합니다. 여기서 n은 지수입니다. squaring은 이것을 O (log (n))로 줄입니다. n의 비트 수를 문제의 크기로 취하면 각 제품의 비트 수를 계산하고 곱셈을 일정 시간 연산으로 간주하지 않을 수도 있습니다. 수치 계산을하는 사람들의 실질적인 관심사에 대해서는 Wikipedia 페이지가 지나치게 현저하다고 생각합니다. 복잡성 - 이론적 인 문제에 대해서는 그 정확성에 의문의 여지가있다. –

1

#include <math.h> 다음 컴파일러는 모두 double하지 int을있는 pow()에 인수의 유형을 모르는되지는 않는 경우 - 그래서 당신은 정의되지 않은 결과를 얻을. 24를 얻으면 16418이됩니다.

+0

OP에는 math.h가 포함됩니다. math.h를 포함하지 않으면 약간의 결과를 얻을 기회가 아닙니다. 따라서 우리는 완전히 다른 문제입니다. –

1

pow를 변수와 함께 사용하면 그 결과는 double이됩니다. int에 할당하면 자릅니다.

pow의 결과를 double 또는 float 변수에 할당하여이 오류를 피할 수 있습니다.

그래서 기본적

x^y로서 정확하게 동일하지 않은 결과 생성한다 exp(log(x) * y)로 변환 - 부동 소수점 값처럼 거의 근사 ,. 따라서 예를 들어 5^224.9999996 또는 25.00002

+0

나는 조종사에게 시험에서 int instant double을 사용하는 것에 대해 물어 보았다. 그는 int, int를 사용했다. 하지만 지금 나는 그가 틀렸다는 것을 알 수 있습니다. – exsnake

+0

교사 보조자는'double '유형을위한 함수를 호출해서는 안되고'정수 '기반 구현을 사용한다고 가정해야한다는 것을 깨달을 필요가 있습니다. – PaulMcKenzie

2

이중형을위한 함수에서 int 결과를 원합니다. 작은 값이 추가되고 정확하게 감산 될 수 있지만

넌 아마도

ele=(int)(0.5 + pow(n,2)); 
/* ^^   */ 
/* casting and rounding */ 
+0

'ele = round (0.5 + pow (n, 2));'를 사용하는 것이 더 좋습니다. 이 경우'pow (n, 2)'는 0보다 작은 결과를 반환하지 않지만, 음수'x'의 경우'y = (int) (0.5 + x)'가 문제가됩니다. – chux

+6

더 좋지 않습니다! 당신은'round (pow (n, 2))'를 사용해야합니다. 반올림하기 전에 0.5를 더하여 다음 정수로 효과적으로 반올림합니다. 'pow (n, 2)'가 25와 엡실론을 반환하면 26이됩니다. – chqrlie

1

Floating-point arithmetic is not exact.

사용해야 상기 pow() 함수는 일반적으로 대수를 곱한 그래서 입력 모두가 정확한 경우에도, 그 결과 작동 아니다. 엄밀하지 않음 부의 경우, 당신은 25

이 이야기의 교훈은 정수에 정수 연산을 사용하고, 실제 인수가있을 때 <math.h> 기능을 의심하는 것보다 오히려 24를 얻을 수 있습니다 있도록 int에 할당하면 항상 절단 승진되거나 절단됩니다. GCC가 -Wfloat-conversion을 추가하지 않으면 GCC가 경고하지 않는다는 것은 불행한 일입니다. (아마도 그러한 전환이 예상되고 원하는 많은 경우가 있기 때문에 -Wall -Wextra에 없습니다.)

정수형의 경우, pow()보다는 곱셈 (음수 인 경우 나눗셈)을 사용하는 것이 더 안전하고 빠릅니다. 필요하면 후자를 예약하십시오! 그래도 오버플로의 위험에 유의하십시오.