固定小数点計算ふたたび

前回の 固定小数点の再発明 - 滴了庵日録 ではROMサイズがかえって増えるという残念な結果になったので、C++でクラス化することはあきらめてC言語で書きなおした。

fixed24.h

#ifndef _FIXED24_H
#define _FIXED24_H

#include<stdint.h>

typedef int32_t fixed24;

#define FIXED24(x, y) (fixed24)(((int64_t)(x) << 24)/(int64_t)(y)) 

fixed24 int_toFixed24(int32_t x, int32_t y);
fixed24 fixed24_mul(fixed24 x, fixed24 y);
fixed24 fixed24_div(fixed24 x, fixed24 y);
int     fixed24_toInt(fixed24 x);
double  fixed24_toDbl(fixed24 x);

#endif

fixed24.c

#include "fixed24.h"

fixed24 int_toFixed24(int32_t x, int32_t y) {
	return (fixed24)(((int64_t)x << 24) / (int64_t)y);
}
fixed24 fixed24_mul(fixed24 x, fixed24 y) {
	return (int32_t)(((int64_t)(x) * (int64_t)(y)) >> 24);
}
fixed24 fixed24_div(fixed24 x, fixed24 y) {
	return (int32_t)((((int64_t)(x) << 32) / (int64_t)(y)) >> 8);
}
int fixed24_toInt(fixed24 x) {
	return (int)((x) >> 24);
}
double fixed24_toDbl(fixed24 x) {
	return (double)x / (double)0x01000000;
}

テスト

#include <stdio.h>
#include <stdlib.h>

#include "fixed24.h"

int main(void)
{
    fixed24 x = FIXED24(10, 1);         // 10/1 = 10
    fixed24 y = int_toFixed24(20, 100); // 20/100 = 0.20
    fixed24 z = 0x01000000 / 2;         // 1/2 = 0.5

    printf("x = %d (%08X)\n", fixed24_toInt(x), x);
    printf("y = %f (%08X)\n", fixed24_toDbl(y), y);
    printf("z = %f (%08X)\n", fixed24_toDbl(z), z);

    z = x + y;
    printf("%f + %f = %f (%08X)\n",
        fixed24_toDbl(x), fixed24_toDbl(y), fixed24_toDbl(z), z);
    z = x - y;
    printf("%f - %f = %f (%08X)\n",
        fixed24_toDbl(x), fixed24_toDbl(y), fixed24_toDbl(z), z);
    z = fixed24_mul(x, y);
    printf("%f * %f = %f (%08X)\n",
        fixed24_toDbl(x), fixed24_toDbl(y), fixed24_toDbl(z), z);
    z = fixed24_div(x, y);
    printf("%f / %f = %f (%08X)\n",
        fixed24_toDbl(x), fixed24_toDbl(y), fixed24_toDbl(z), z);
    z = x * 2;
    printf("%f * 2 = %f (%08X)\n", fixed24_toDbl(x), fixed24_toDbl(z), z);
    z = x / 2;
    printf("%f / 2 = %f (%08X)\n", fixed24_toDbl(x), fixed24_toDbl(z), z);

    x = FIXED24(1, 1);
    y = FIXED24(1, 1);
    printf("%f == %f : %s\n",
        fixed24_toDbl(x), fixed24_toDbl(y), (x == y) ? "TRUE" : "FALSE");
    printf("%f != %f : %s\n",
        fixed24_toDbl(x), fixed24_toDbl(y), (x != y) ? "TRUE" : "FALSE");
    y = FIXED24(2, 1);
    printf("%f == %f : %s\n",
        fixed24_toDbl(x), fixed24_toDbl(y), (x == y) ? "TRUE" : "FALSE");
    printf("%f != %f : %s\n",
        fixed24_toDbl(x), fixed24_toDbl(y), (x != y) ? "TRUE" : "FALSE");

    return 0;
}