C# static

카테고리 없음 2018. 12. 29. 20:10

static 한정자


- 특정 개체가 아니라 형식 자체에 속하는 정적 멤버를 선언할 수 있음

- 클래스, 필드, 메서드, 프로퍼티, 연산자, 이벤트, 생성자와 같이 사용 가능

- 인덱서, 소멸자에 사용 불가


=> 모든 정보가 인스턴스가 아니고 클래스에 담긴다고 생각하면 됨




static method


- Non Static Method 보다 속도가 빠름

- 인스턴스의 객체 멤버 참조 불가능

- 클래스 명을 통해서 사용 


NonStaticClass.StaticMethod();

- 파라미터 전달 가능


class NonStaticClass
{
    public int nonStaticField;
    public static int staticField;
    public static void StaticMethod(int inputValue)
    {
        staticField = inputValue;
    }
}

public static void Main()
{
    NonStaticClass.StaticMethod(7);
}



static field


- 인스턴스가 아닌 클래스에 속하므로 실행될 때 한번 초기화되고 계속 동일한 메모리를 사용

- Non Static Field는 인스턴스 생성할 때 마다 인스턴스에 할당되어 생기는 반면 static Field는 한 개만 존재





static class


- 프로그램이 로드될 때 정적 생성자가 한번 호출되면서 메모리에 로드됨

- 생명주기는 프로그램이 살아있는 동안이므로 프로그램이 종료되거나 crash 발생하는 경우에 해제됨

- 클래스를 인스턴스화 할 수 없음 (new 사용 불가)

- 정적 멤버만 포함(생성자도 마찬가지)

- static 생성자는 프로그램이 로드되고 난 직후 실행됨, 보통 static field를 초기화하는 경우에 사용


static class StaticClass
{
    public static int staticField;
           
    static StaticClass()
    {
        System.Console.WriteLine(staticField);
        staticField = 5;
    }
}

public static void Main()
{
    // 0이 먼저 출력되고
    System.Console.WriteLine(StaticClass.staticField);  //여기서 5가 출력됨
}


cf) static클래스는 static 멤버와 private 생성자만 포함된 클래스와 동일한 역할



Posted by @히테
,

부동소수점

카테고리 없음 2018. 12. 25. 16:38

1. 컴퓨터가 실수를 표현하는 방법


* 고정 소수점 : 정수부와 소수부로 나누어서 표현하는 방법

 - int와 다를게 없어서 연산속도가 빠르고 시스템이 간단함

 - 표현할 수 있는 수의 크기가 작음

 - 정밀도를 높이려면 필요한 비트 수가 커짐


* 부동 소수점 : 가수부와 지수부로 나누어서 표현하는 방법

 - 넓은 범위의 숫자를 표현할 수 있음

 - 상대적으로 정밀도가 높음

 - 연산이 복잡해짐







2. 2진법으로 된 부동소수점


IEEE 754 : IEEE에서 공표한 부동 소수점 방식의 표준안




s (부호) : 첫번째 비트, 수의 부호를 결정


m (가수) : 2진수에서는 1.xxxx.. 로 이루어짐

 - 단정도(32비트) : 23비트

 - 배정도(64비트) : 52비트


e (지수) : m을 정규화 하면 정해지는 값, IEEE 754에서는 비트로 표현하는경우 e + bias가 들어가게 된다

 - 단정도(32비트) : 8비트

 - 배정도(64비트) : 11비트




* 예시) -27.625


-27.625 (10진수) = 11011.101 (2진수)


s (부호) => 

 -1 이므로 비트는 1


m (가수) => 

 - 11011.101을 4칸 이동시킴 : 1.1011101

 - 소수 부분만 남김 : 1011101

 - 나머지는 0으로 채움 : 1011101000...


e (지수) : m을 정규화 하면 정해지는 값, IEEE 754에서는 비트로 표현하는경우 e + bias가 들어가게 된다

 - 4칸 이동이므로 2 ^ 4 : e는 4

 - IEEE 754에서는 bias값은 127 이므로 4 + 127 = 131

 - 이진법 변환 : 10000011


1100000111011101000...







3. 부동소수점 오류


* 0.1을 소수점 9자리까지 출력했을 때



float value = 0.1f;
Console.WriteLine("{0:G9}", value);  //0.100000001


=> 실제로 근사치를 갖고 있음



* 0.1과 0.100000001490116119384765625을 비교했을 때


float num = 0.1f;
if(num == 0.100000001490116119384765625)
{
     Console.WriteLine("True"); // 출력
}

=> 다음과 같이 정확한 값을 갖고 있지 않아서 연산에도 오류가 생긴다


* int형으로 캐스팅



float value = 43.3f - 43.2f;
 Console.WriteLine("{0:G9}", value); //0.0999984741

 value = value * 10;
 Console.WriteLine("{0:G9}", value); //0.999984741

 int valueInt = (int)value;
 Console.WriteLine(valueInt); //0


=> 원하는 값은 0.1, 1, 1 이어야하지만 실제로 갖고있는 실수값이 근사값이기 때문에 int로 형변환 시 의도하던 값과 다른 값이 나옴








4. 오류 해결 방법


* float보다는 double 사용

 - float의 상대오차 10^-7, double의 상대오차 10^-15 

 - C# decimal : 부동소수형이 아니고 29자리까지 지원


* 바로 캐스팅하지 말고 작은 숫자만큼 더한 후 캐스팅


* 등호사용 금지(내결함성 허용) : epsilon 사용



double value = 43.3f - 43.2f;

if(value >= 0.1)
{
    Console.WriteLine("Yes!");
}
else
{
    Console.WriteLine("No!"); // No! 출력
}

if (Math.Abs(value) <= 0.1f + double.Epsilon)
{
    Console.WriteLine("Yes!"); // Yes! 출력
}
else
{
    Console.WriteLine("No!");
}

=> 최대한 실수형 간 계산을 피하기

Posted by @히테
,




27.625 를 변환해보자



1. 정수부 변환




27 = 

1  * 2^0 + 

1  * 2^1  + 

0 * 2^2 + 

1  * 2^3 + 

1  * 2^4



27 (10진수) = 11011 (2진수)



2. 소수부 변환


1이 넘는 부분은 정수부를 버림


0.625 (10진수) = 0.101 (2진수)


단 소수점을 변환할 때 무리수가 되는 경우가 있는데 적당히 잘르면 됨(다음과 같은 방법으로 8진수, 16진수로도 변환 가능)






27.625 (10진수) = 11011.101 (2진수)

Posted by @히테
,