1

저는 Fixedpoint 클래스를 작성하고 있지만 약간의 문제가 있습니다 ... 곱셈, 나누기 부분, 에뮬레이션 방법을 잘 모르겠습니다. 부서 운영자에게 아주 힘든 찌르다가 잘못했다고 확신합니다. 지금까지 보이는 모습은 다음과 같습니다.C++ : 에뮬레이션 된 고정 소수점 나누기/곱셈

class Fixed 
{ 
    Fixed(short int _value, short int _part) : 
     value(long(_value + (_part >> 8))), part(long(_part & 0x0000FFFF)) {}; 

    ... 

    inline Fixed operator -() const // example of some of the bitwise it's doing 
    { 
     return Fixed(-value - 1, (~part)&0x0000FFFF); 
    }; 

    ... 

    inline Fixed operator/(const Fixed & arg) const // example of how I'm probably doing it wrong 
    { 
     long int tempInt = value<<8 | part; 
     long int tempPart = tempInt; 
     tempInt /= arg.value<<8 | arg.part; 
     tempPart %= arg.value<<8 | arg.part; 
     return Fixed(tempInt, tempPart); 
    }; 

    long int value, part; // members 
}; 

나는 아주 좋은 프로그래머가 아닙니다. 하하!

클래스의 'part'는 16 비트 너비이지만 (고정 오버플로가 발생하기 전에 가능한 오버플로 공간이 필요하다고 생각하기 때문에 긴 32 비트로 표현됩니다) 동일한 '정수'값 부품. 'part'가 연산 중 하나에서 0xFFFF를 넘으면 최상위 16 비트가 'value'에 추가 된 다음 부분이 마스크되어 최하위 16 비트 만 남습니다. 그것은 init 목록에서 수행됩니다.

내가 묻는 것이 싫지만 누구나 내가 이런 식으로 문서를 찾을 수있는 곳을 알거나 "트릭"또는이 두 연산자를 수행하는 방법을 알고 있다면 나는 그것을 매우 기쁘게 생각한다. 나는 수학에 관한 한 어리 석다. 나는 누군가가 이것을해야만한다는 것을 알고있다. 그러나 검색 구글은 한번 약속의 땅으로 나를 데려가 지 않는다. ...

+0

이 숙제가 있습니까? 근본적으로 부동 소수점 수학을 모방하려하지만 부동 소수점 표기법을 사용하지 않고 있습니까? IEEE가 이것을 어떻게 처리하는지 보셨습니까? –

+0

@Zac 슬프게도, 프로그래밍 학교에 다녀 본 적이 없거나 아무 것도 말할 수 없었습니다! 이것은 내가하고있는 2 차원 물리 엔진에서 부동 소수점 연산을 피하려는 아주 가난한 시도입니다. 하지만 지금은 IEEE 인터넷 검색, 그래서 내가 볼게요! –

+0

@Zac : OP는 '고정 된'포인트 멀티 및 분할에 관한 것이지 '부동'지점이 아니라는 점에서 차이가 있습니다. http://en.wikipedia.org/wiki/Fixed-point_arithmetic –

답변

2

Jan이 말한 것처럼 단일 정수를 사용하십시오. 16 비트 정수 및 소수 부분을 지정하는 것처럼 보이므로 일반 32 비트 정수로이 작업을 수행 할 수 있습니다.

"속임수"는 작업을 수행 할 때 숫자의 "형식"이 어떻게되는지 알기위한 것입니다. 귀하의 형식은 16.16으로 설명됩니다. 더하거나 뺄 때 형식은 그대로 유지됩니다. 곱하면 32.32가됩니다. 결과에 64 비트 임시 값이 필요합니다. 그런 다음 16 진수 변환을하여 48.16 형식으로 가져온 다음 16.16에서 아래 32 비트를 사용하여 답을 얻으십시오.

나는 부분적으로 녹슬 었어. DSP에서, 내가 이걸 배웠던 곳에서 가능한 한 비싼 부분을 피했다.

+0

실제로 맞을 것 같네요! 좋아, 단 하나의 32 비트 정수를 사용하여, 내가 왜 처음에 그걸 가지 않았는지 확신하지 못한다. 그리고 ... 아하, 곱셈 부분이 너무 힘들게 보였습니다. 나는 그것이 전체 시련이라고 생각했다. 나는 지금 나를위한 부서 부분을 찾는 문제 일 뿐이라고 생각한다. 고맙습니다! –

+0

@Clairvoire : [Zac이 링크 된 기사] (http://en.wikipedia.org/wiki/Fixed-point_arithmetic#Operations)는 더 일반적인 경우에 나누기 연산에 대한 세부 정보를 제공합니다. 여기서 배율 인수는 ' 두 피연산자에 대해 t 2^16입니다. 그렇게하면 충분할 것입니다. –

0

하나의 정수를 사용하는 것을 권장한다. 값은 별도의 전체 및 분수 부분 대신 사용됩니다. 덧셈과 뺄셈보다 직접 integeral 대응이 있고 당신은 단순히 모든 일반적인 컴파일러는 이러한 일이 64 비트 지원, 사용할 수 있습니다

  • 곱셈 :

    operator*(const Fixed &other) const { 
        return Fixed((int64_t)value * (int64_t)other.value); 
    } 
    
  • 부문 :

    operator/(const Fixed &other) const { 
        return Fixed(((int64_t)value << 16)/(int64_t)other.value); 
    } 
    

64 비트 정수는

입니다.
  • gcc에서 std:: 네임 스페이스에있는 cstdint (또는 cstdint)을 사용할 수 있어야하므로 위에서 언급 한 유형을 사용할 수 있습니다. 그렇지 않으면 32 비트 대상에 long long이고 64 비트 대상에는 long입니다.
  • Windows의 경우 항상 long long 또는 __int64입니다.
+3

이것은 고정 소수점을 망칠 것입니다. 다시 곱하기를 얻으려면 비트 시프트가 필요합니다. –

+0

나는 지정해야하지만, 나머지 부분을 버리지 않고 정상적인 사업부와 유사한 방식으로 행동하는 것이 좋겠다. 그러나 그것은 나에게 아이디어를 준다! –

0

일을 시작하려면 먼저 (단항) inverse(x) = 1/x을 구현 한 다음 a/ba*inverse(b)으로 구현하십시오. 중간체를 32.32 형식으로 나타내려고합니다.

+0

절대로 그 수술을 생각하지 못했습니다 ... 어떻게 내 머리를 감싸려고 노력하고 있지만, 분열을하기 위해서는 어느 쪽이든해야 할 필요가 있습니다! 머리를 주셔서 감사합니다! –

+0

가장 쉬운 솔루션은'(1 << 31)/(x * 65536) << 1'입니다. 첫 번째 부분은 어쨌든 상수이고,'(x * 65536)'는 16.16 fp 번호를 32 비트 정수로 재 해석 한 것입니다. 결과는 32 비트 정수'(1/x) * 65536'이 될 것이고, 당신은 16.16 역수로서 쉽게 재 참 할 수 있습니다. 단점 :''31'' /'<< 1'은 LSB가 손실되었다는 것을 의미합니다. – MSalters

관련 문제