양의 정수를 이진법으로 표현할 때 자리수를 구하는 C 언어 함수를 두 가지로 구현해 보았다.
함수 int nbits(int) 는 주어진 정수를 직접 2로 나누기를 반복하면서 자리수를 구한 것이고,
함수 int bits(int) 는 밑이 2인 로그함수 lg(x) = log(x)/log(2) 를 이용하여 구한 것이다.
그런데 Cygwin 또는 Linux 에서 gcc 로 컴파일하여 실행하면 오루가 빌생한다. (참고로 gcc 의 버전은 4.5.3 이다.) MinGW 의 gcc 는 버전이 4.6.2 인데 마찬가지로 log 계산에 오류가 있다.
Visual C, C#, Java, Python 으로는 2100000000 이하의 양의 정수에 대하여 그런 오류가 발생하지 않는다.
//
// 1) Calculate the number of bits of binary format of a given positive integer,
// 2) Compare it with lg(n) + 1 = log(n)/log(2) + 1
//
// Compiling with Visual C++ 10.
// Compile: cl calcLG64.c
// Execute: calcLG64
//
// Or
//
// Compiling with GCC on Cygwin.
// Compile: gcc -o calcLG64.exe calcLG64.c
// Execute: ./calcLG64
//
// Date: 2013. 2. 25.
// Author: pkim __AT__ scripts ((DOT)) pe ((DOT)) kr
#include <stdio.h>
#include <math.h>
int nbits(int n)
{
int i = 0;
while (n > 0) {
n >>= 1;
i++;
}
return i;
}
double bits(int n)
{
return (int) (log((double)n)/log(2.0)) + 1;
}
int main()
{
int i;
int k1, k2;
for (i = 1; i <= 65537; i++)
{
k1 = nbits(i);
k2 = bits(i);
if (k1 != k2) {
printf("%7d: k1 = nbits(%5d) = %2d", i, i, k1);
printf(", k2 = lg(%5d) + 1 = %2d\n", i, k2);
}
}
return 0;
}
/*
Output with G++ on Cygwin
8: k1 = nbits( 8) = 4, k2 = lg( 8) + 1 = 3
64: k1 = nbits( 64) = 7, k2 = lg( 64) + 1 = 6
128: k1 = nbits( 128) = 8, k2 = lg( 128) + 1 = 7
4096: k1 = nbits( 4096) = 13, k2 = lg( 4096) + 1 = 12
8192: k1 = nbits( 8192) = 14, k2 = lg( 8192) + 1 = 13
16384: k1 = nbits(16384) = 15, k2 = lg(16384) + 1 = 14
32768: k1 = nbits(32768) = 16, k2 = lg(32768) + 1 = 15
*/
/*
Output with Visual C++ 10 on Windows XP:
*/
또 다음은 C++ 언어로 작성한 것인데, g++ 로 컴파일하여 실행한 것도 역시 log 계산에 오류가 있음을 보여준다.
// Filename: calcLG64.cpp
//
// 1) Calculate the number of bits of binary format of a given positive integer,
// 2) Compare it with lg(n) + 1 = log(n)/log(2) + 1
//
// Compiling with Visual C++ 10.
// Compile: cl /EHsc calcLG64.cpp
// Execute: calcLG64
//
// Or
//
// Compiling with G++ on Cygwin.
// Compile: g++ -o calcLG64 calcLG64.cpp
// Execute: ./calcLG64
//
// Date: 2013. 2. 23.
// Author: pkim __AT__ scripts ((DOT)) pe ((DOT)) kr
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
#include <iomanip>
using std::setw;
int nbits(int n)
{
int i = 0;
while (n > 0) {
n >>= 1;
i++;
}
return i;
}
double bits(int n)
{
return (int) (log((double)n)/log(2.0)) + 1;
}
int main()
{
int i;
int k1, k2;
for (i = 1; i <= 65537; i++)
{
k1 = nbits(i);
k2 = bits(i);
if (k1 != k2) {
cout << setw( 7 ) << i << ": k1 = nbits(" << setw( 5 ) << i << ") = " << setw( 2 ) << k1;
cout << ", k2 = lg(" << setw( 5 ) << i << ") + 1 = " << setw( 2 ) << k2 << endl;
}
}
}
/*
Output with G++ on Cygwin
8: k1 = nbits( 8) = 4, k2 = lg( 8) + 1 = 3
64: k1 = nbits( 64) = 7, k2 = lg( 64) + 1 = 6
128: k1 = nbits( 128) = 8, k2 = lg( 128) + 1 = 7
4096: k1 = nbits( 4096) = 13, k2 = lg( 4096) + 1 = 12
8192: k1 = nbits( 8192) = 14, k2 = lg( 8192) + 1 = 13
16384: k1 = nbits(16384) = 15, k2 = lg(16384) + 1 = 14
32768: k1 = nbits(32768) = 16, k2 = lg(32768) + 1 = 15
*/
/*
Output with Visual C++ 10 on Windows XP:
*/
gcc 에는 2를 밑으로 하는 로그함수 log2 기 이미 구현되어 있다. 그래서 log2(8) 을 테스트해보았는데, floor(log2(8)) 에 대하여 역시 오류가 발생한다. 신기한 것은 옵션 -std=c99 -lm 을 붙여서 컴파일하여 실행하면 오류가 발생한다는 점이다. (참고로, Visual C++ 는 Visual Studio 2012 에서 처음으로 log2 함수가 지원된다.)
//
// Compile: gcc -o test_log2 test_log2.c
// Compile: gcc -o test_log2 test_log2.c -std=c99 -lm
// Execute: ./test_log2 [number]
//
// See: http://www.linuxquestions.org/questions/programming-9/log2-not-found-367355/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
// #include <amp_math.h> // for log2()
// supported in Visual Studio 2012
// See: http://msdn.microsoft.com/en-us/library/hh308239.aspx
int main( int argc, char *argv[] )
{
double log_base_2 = 0;
double given_value;
if( argc < 2 )
{
fprintf( stderr, "ERROR! You must give a numeric argument!\n" );
return 1;
}
given_value = strtod( argv[1], NULL );
log_base_2 = log2( given_value );
printf( "Log base 2 of %f is %f\n",
//printf( "Log base 2 of %f is %.15f\n",
given_value,
log_base_2 );
printf( "Floor of log base 2 of %f is %f\n",
given_value,
floor(log_base_2) );
return 0;
}
/*
Compile and Execute:
$ gcc -o test_log2 test_log2.c
$ ./test_log2 8
Log base 2 of 8.000000 is 3.000000
Floor of log base 2 of 8.000000 is 3.000000
Compile and Execute:
$ gcc -o test_log2 test_log2.c -std=c99 -lm
$ ./test_log2 8
Log base 2 of 8.000000 is 3.000000
Floor of log base 2 of 8.000000 is 2.000000
*/
'프로그래밍 > C' 카테고리의 다른 글
Visual C 2010 으로 컴파일하여 실행해 본 OpenGL 예제: Redbook 의 Teapots (0) | 2013.05.17 |
---|---|
Visual C 2010 으로 컴파일하여 실행해 본 OpenGL 예제: Redbook 의 Cube (0) | 2013.05.10 |
부정확한 부동소수점수 계산에 대하여 (0) | 2013.01.22 |
(C 언어로 구현해 보는) 십진법의 신비: 숫자 계산 피라미드 세 가지 (0) | 2013.01.22 |
MinGW 의 MSYS 에서 more 명령이 없다고 할 때 (0) | 2013.01.15 |