Как работает простое преобразование с фиксированной точкой? - PullRequest
0 голосов
/ 08 мая 2020

Думаю, я понимаю, что происходит при преобразовании значений в представление с фиксированной запятой с помощью следующего кода. Используйте 2-битную для целой части и 30-битную для дробной части числа, чтобы мы получили результирующий диапазон от -2.0 до 1.999999999

#include <bitset>
#include <cmath>
#include <iomanip>
#include <iostream>

unsigned int transformForTransfer(double value){
    int integer;
    unsigned int shiftedInteger;
    double fraction;
    if(value >= 0){
        integer = (int32_t)value;
        fraction = value - integer;
        shiftedInteger = (unsigned int)(integer << 30);
    }
    else{
        integer = -2;
        fraction = 2.0 + value;
        shiftedInteger = 0x80000000;
    }

    auto fractionPart = (unsigned int)round(fraction * std::pow(2, 30));
    std::cout << "fraction part          : " << std::bitset<sizeof(fractionPart) * 8>(fractionPart) << std::endl;
    std::cout << "integer part           : " << std::bitset<sizeof(integer) * 8>(integer) << std::endl;
    auto result = (shiftedInteger | fractionPart);
    auto bits = std::bitset<sizeof(result) * 8>(result).to_string();
    std::cout << "value bits unsigned int: " << bits << std::endl;
    return result;
}

Но зачем использовать этот простой подход:

unsigned int doubleToTransfer(double value)
{
    return (unsigned int)(round(value * std::pow(2, 30)));
}

приведет к тому же результату:

int demoInt = -2000000000;
double demo;
while (demoInt < 1999999999){
    demoInt += 1;
    demo = demoInt * 1E-09;
    if(transformForTransfer(demo) != doubleToTransfer(demo)){
        // never reached
        std::cout << " != " << demo << std::endl;
    }
}
...