Search code examples
cfloating-pointfloating-point-conversion

How to test fixed point library?


I need to develop a math library using fixed point arithmetic. I need to test this library.

For testing it, I need to do the following:

  1. read floating point number.
  2. Convert it into fixed point number
  3. Do all operation using fixed point arithmetic
  4. Convert result into floating point
  5. write o/p (floating point number

But I don't want to use float / double in my test cases. So how I will perform Step-1 and step-5?


Solution

  • Integer input is obviously easily done without floating points. If you don't know how to do that, please read the questions on this site for how to do that (or study the first part of this function). Decimals are relatively simple in a generic sense, simply keep reading as an integer, but keep track of how many digits you read after the decimal, and then divide the input-value by 10^digit_count. Easy.

    fixed_point input(source)
    {
        fixed_point value = 0;
        fixed_point shift = 1;
        char nextchar;
        //read integer part
        while(nextchar = source.get_next() && nextchar>='0' && nextchar<='9') {
            auto digit = nextchar-'0';
            value = value * base + digit;
        }
        //if there's a decimal...
        if (nextchar == '.') {
            //then read the fractional part 
            while(nextchar = source.get_next() && nextchar>='0' && nextchar<='9') {
                auto digit = nextchar-'0';
                value = value * base + digit;
                shift = shift * 10;
            }
            //at this point, if input was "123.456"
            //we have a value of "123456",
            //and a shift of 1000.  Simple division.
            value /= shift;
        }
        return value;
    }
    

    and output:

    void output(sink, fixed_point value) {
        fixed_point exponent = 1;
        //find largest base10 exponent that's less than value
        {
            fixed_point check_exponent = exponent *10;
            while(check_exponent >= fixed_point) {
                exponent = check_exponent;
                check_exponent = exponent *10;
            }
        }
        //write integer part
        do {
            sink.write(int(value)/exponent +'0');
            value -= int(value)/exponent*exponent;
            exponent /= 10;
        } while(exponent > 0);
        //if there's a fraction
        if (value > 0) {
            sink.write('.');
            int max_digits = 6;  //or something
            //write up to 6 digits
            while(value>0 && max_digits) {
                value *= 10;
                sink.write(int(value));
                value -= int(value);
                max_digits -= 1;
            }
        }
    }
    

    Note that this code elides many small details, such as the digit type, negatives, how source.get_next() works, and overflows. Also note that in real code you want to source.peek() (or equivalent), and only consume the character if it's a digit or ., so you leave trailing invalid digits in the source buffer. None of this comes even close to compiling, and probably has many semantical errors and oversights even if it did compile. Note that depending on your base, the output may have infinite digits in base 10, so having a limit on digits output is very important.