0

catch가 있습니다!float를 정수로 변환

IEEE 754 두 개의 연속 16 비트 정수로 저장된 단 정밀도 (32 비트) 부동 소수점을가집니다.

사용중인 프로세서에 부동 소수점 연산 또는 부동 소수점 데이터 유형이 없습니다! 내가 원하는 것은 float 값을 16 비트 부호있는 정수로 변환하는 것입니다. 프로세서에는 표준 정수 연산과 비트 조작 (마스킹, 시프 팅 등)이 있습니다.

32 비트 부동 소수점에서 16 비트 정수로 갈 때 정밀도를 약간 잃어 버릴 필요가 있다는 것을 제외하고는. 정수에는 문제의 값 범위를 기반으로하는 묵시적 스케일링 계수가 필요합니다.

다음은 간단한 예입니다. float의 범위가 0.00에서 10.00 인 경우 이 경우 정수의 범위는 0 to 1000입니다. 이 경우 정수의 척도는 100입니다.

IEEE 754은 1 부호 비트, 지수 (8 비트 바이어스) 및 23 비트 가수.

난 플로트의 구성 부분의 값을 재구성하기 위해 방정식을 알고있다 :

실수 값 = (-1)^Sign_bit * (1 + 가수) * 2^(지수-127).

내가 볼 수있는 주요 문제는 16 비트 부호있는 정수 (-32768 ~ +32767 범위)로 작업하고 오버플로 또는 언더 플로우를 피하는 것입니다.

+1

나는 당신이 원하는 것을 이해하지 못합니다. –

답변

0

32 비트 부동 소수점을 16 비트 정수로 변환하려고합니다. 그러나, 당신이주는 예제는 소수점 스케일링을 사용하고 바이너리는 사용하지 않습니다. 부동 소수점 유닛이없는 시스템에서 이진 도메인에서 계속 작업하고 싶거나 실제로 소수의 표현으로 변환하려는 경우 확실하지 않습니다.

여기서 나는 부동 소수점 명령어에 대한 액세스 권한이 없다고 가정합니다. 당신은 프로그래밍 언어를 지정하지 않았으므로 C#에서 코드를 코딩하기로 결정했습니다. 언어는 사용하기 쉽지만 아마도 비트 바이올린에 가장 적합하지는 않습니다. C 또는 C++에서 이것을 구현하는 것이 더 쉽고 효율적이라는 것을 알 수 있습니다.

2 진 표현을 계속 사용하기 때문에 10 또는 100 (10의 정수)의 숫자가 될 수는 없지만 대신 2의 정수가되어야합니다. 다음은 IEEE 754 binary 32 부동 소수점 수.

class Ieee754Binary32 { 

    public Ieee754Binary32(Single value) { 
    using (var memoryStream = new MemoryStream()) { 
     var binaryWriter = new BinaryWriter(memoryStream); 
     binaryWriter.Write(value); 
     memoryStream.Seek(0, SeekOrigin.Begin); 
     var binaryReader = new BinaryReader(memoryStream); 
     var bits = binaryReader.ReadInt32(); 
     Fraction = bits & 0x7FFFFF; 
     Exponent = ((bits >> 23) & 0xFF) - 127; 
     Sign = (bits & 80000000) == 1 ? -1 : 1; 
    } 
    } 

    public Int32 Fraction { get; private set; } 

    public Int32 Exponent { get; private set; } 

    public Int32 Sign { get; private set; } 

    public Int16 ToScaledInt16(Int32 scaling) { 
    if (Exponent == -127 && Fraction == 0) 
     return 0; 
    var mantissa = 0x8000 | (Fraction >> 8); 
    var unscaledInt32 = Exponent >= 0 ? mantissa << Exponent : mantissa >> -Exponent; 
    var scaledInt16 = unscaledInt32 >> (15 - scaling); 
    return (Int16) (Sign*scaledInt16); 
    } 

} 

사용 방법은 ToScaledInt16입니다. 8의 분수를 사용하여 숫자를 표현하려면 에 3 값을 제공해야합니다. 모든 숫자에 2^3 = 8을 곱합니다. 0.125 = 1/8을 1로 변환하면 0.25 = 2/8에서 2 등이됩니다.

이 코드는 반올림, NaN 또는 오버플로와 같은 복잡한 항목을 처리하지는 않지만 시작 지점으로 사용할 수 있습니까?