Back to TILs

C++ fixed_point_01

Date: 2024-06-09Last modified: 2024-06-09

Table of contents


  // Use differents amounts of bits for fractional part
  for( uint32_t SHIFT_AMOUNT : { 28, 24, 16, 8 } ) {

    // Utility for printing
    auto print_binary = [SHIFT_AMOUNT]( uint32_t value, auto comment ) {
      std::bitset<32> bits{ value };
      std::string     value_string = bits.to_string();
      value_string.insert( 32 - SHIFT_AMOUNT, "📍" );
      std::cout << value_string << "\t" << value << "\t" << comment << std::endl;
    };

    uint32_t SHIFT_MASK = ( 1 << SHIFT_AMOUNT ) - 1;
    std::cout << "====================================================" << std::endl;
    std::cout << "SHIFT_AMOUNT = " << SHIFT_AMOUNT << std::endl;
    std::cout << "SHIFT_MASK = " << SHIFT_MASK << std::endl;

    print_binary( SHIFT_MASK, "SHIFT_MASK" );

    uint32_t price = 500 << SHIFT_AMOUNT;

    if( ( price >> SHIFT_AMOUNT ) != 500 ) {
      std::cout << "⛔ no enought bits for integer part holds our example" << std::endl;
    }

    print_binary( price, "price = 500" );

    price += 10 << SHIFT_AMOUNT;
    print_binary( price, "price += 10" );

    price *= 3;
    print_binary( price, "price *= 3" );

    price /= 4; // now our price is ((500 + 10) * 3) / 4 = 382.5
    print_binary( price, "price /= 4" );

    // C style print
    printf( "price integer is %d\n", price >> SHIFT_AMOUNT );
    printf( "price fraction is %d\n", price & SHIFT_MASK );
    printf( "price fraction in decimal is %f\n", ( (double)( price & SHIFT_MASK ) / ( 1 << SHIFT_AMOUNT ) ) );

    std::cout << std::endl;
  }

Possible output

====================================================
SHIFT_AMOUNT = 28
SHIFT_MASK = 268435455
0000📍1111111111111111111111111111	268435455	SHIFT_MASK
⛔ no enought bits for integer part holds our example
0100📍0000000000000000000000000000	1073741824	price = 500
1110📍0000000000000000000000000000	3758096384	price += 10
1010📍0000000000000000000000000000	2684354560	price *= 3
0010📍1000000000000000000000000000	671088640	price /= 4
price integer is 2
price fraction is 134217728
price fraction in decimal is 0.500000

====================================================
SHIFT_AMOUNT = 24
SHIFT_MASK = 16777215
00000000📍111111111111111111111111	16777215	SHIFT_MASK
⛔ no enought bits for integer part holds our example
11110100📍000000000000000000000000	4093640704	price = 500
11111110📍000000000000000000000000	4261412864	price += 10
11111010📍000000000000000000000000	4194304000	price *= 3
00111110📍100000000000000000000000	1048576000	price /= 4
price integer is 62
price fraction is 8388608
price fraction in decimal is 0.500000

====================================================
SHIFT_AMOUNT = 16
SHIFT_MASK = 65535
0000000000000000📍1111111111111111	65535	SHIFT_MASK
0000000111110100📍0000000000000000	32768000	price = 500
0000000111111110📍0000000000000000	33423360	price += 10
0000010111111010📍0000000000000000	100270080	price *= 3
0000000101111110📍1000000000000000	25067520	price /= 4
price integer is 382
price fraction is 32768
price fraction in decimal is 0.500000

====================================================
SHIFT_AMOUNT = 8
SHIFT_MASK = 255
000000000000000000000000📍11111111	255	SHIFT_MASK
000000000000000111110100📍00000000	128000	price = 500
000000000000000111111110📍00000000	130560	price += 10
000000000000010111111010📍00000000	391680	price *= 3
000000000000000101111110📍10000000	97920	price /= 4
price integer is 382
price fraction is 128
price fraction in decimal is 0.500000


References