Question

I'm trying to solve exercise 2-1 from "The C Programming Language", 2nd edition, which asks to:

"Write a program to determine the ranges of char, short, int, and long variables, both signed and unsigned, by printing appropriate values from standard headers and by direct computation. Harder if you compute them: determine the ranges of the various floating-point types."

I've managed to determine the ranges of all types except floating-points, both by using minimum and maximum values from standard headers and by direct computation.

How do I determine the ranges of floating-point types using direct computation?

#include <stdio.h>
#include <limits.h>
#include <float.h>

#define TESTBIT 2

/* write a program to determine the ranges of char, short, int, and long variables,
   both signed and unsigned by printing appropriate values from standard headers
   and by direct computation

   harder if you compute them - determine the ranges of the various floating-point types */
main()
{
    char ch, chtest;
    unsigned char uch;
    short sh, shtest;
    unsigned short ush;
    int i, itest;
    unsigned int ui;
    long l, ltest;
    unsigned long ul;
    long long ll, lltest;
    unsigned long long ull;

    ch = uch = sh = ush = i = ui = l = ul = ll = ull = 0;
    ++ch;        /* Maximum and minimum ranges using direct computation */
    chtest = 0;
    while (chtest >= 0) {
        chtest = ch * TESTBIT;
        if (chtest > 0)
            ch = ch * TESTBIT;
    }
    ch = ch * 2;
    printf("Minimum range of signed char variable: %d\n", ch);

    --ch;
    printf("Maximum range of signed char variable: %d\n", ch);

    --uch;
    printf("Maximum range of unsigned char variable: %u\n", uch);

    ++sh;
    shtest = 0;
    while (shtest >= 0) {
        shtest = sh * TESTBIT;
        if (shtest > 0)
            sh = sh * TESTBIT;
    }
    sh = sh * 2;
    printf("Minimum range of signed short variable: %d\n", sh);

    --sh;
    printf("Maximum range of signed short variable: %d\n", sh);

    --ush;
    printf("Maximum range of unsigned short variable: %u\n", ush);

    ++i;
    itest = 0;
    while (itest >= 0) {
        itest = i * TESTBIT;
        if (itest > 0)
            i = i * TESTBIT;
    }
    i = i * 2;
    printf("Minimum range of signed int variable: %d\n", i);

    --i;
    printf("Maximum range of signed int variable: %d\n", i);

    --ui;
    printf("Maximum range of unsigned int variable: %u\n", ui);

    ++l;
    ltest = 0;
    while (ltest >= 0) {
        ltest = l * TESTBIT;
        if (ltest > 0)
            l = l * TESTBIT;
    }
    l = l * 2;
    printf("Minimum range of signed long variable: %d\n", l);

    --l;
    printf("Maximum range of signed long variable: %d\n", l);

    --ul;
    printf("Maximum range of unsigned long variable: %lu\n", ul);

    ++ll;
    lltest = 0;
    while (lltest >= 0) {
        lltest = ll * TESTBIT;
        if (lltest > 0)
            ll = ll * TESTBIT;
    }
    ll = ll * 2;
    printf("Minimum range of signed long long variable: %lld\n", ll);

    --ll;
    printf("Maximum range of signed long long variable: %lld\n", ll);

    --ull;
    printf("Maximum range of unsigned long long variable: %llu\n", ull);

    printf("\nSize of char: %d\n", CHAR_BIT);    /* Max and min ranges using limits.h and float.h header */
    printf("Minimum range of signed char variable: %d\n", SCHAR_MIN);
    printf("Maximum range of signed char variable: %d\n", SCHAR_MAX);
    printf("Maximum range of unsigned char variable: %u\n", UCHAR_MAX);
    printf("Minimum range of signed short variable: %d\n", SHRT_MIN);
    printf("Maximum range of signed short variable: %d\n", SHRT_MAX);
    printf("Maximum range of unsigned short variable: %u\n", USHRT_MAX);
    printf("Minimum range of int variable: %d\n", INT_MIN);
    printf("Maximum range of int variable: %d\n", INT_MAX);
    printf("Maximum range of unsigned int variable: %u\n", UINT_MAX);
    printf("Minimum range of signed long variable: %ld\n", LONG_MIN);
    printf("Maximum range of signed long variable: %ld\n", LONG_MAX);
    printf("Maximum range of unsigned long variable: %lu\n", ULONG_MAX);
    printf("Minimum range of long long variable: %lld\n", LLONG_MIN);
    printf("Maximum range of long long variable: %lld\n", LLONG_MAX);
    printf("Maximum range of unsigned long long variable: %llu\n\n", ULONG_LONG_MAX);
    printf("Minimum range of float variable: %f\n", FLT_MIN);
    printf("Maximum range of float variable: %f\n", FLT_MAX);
    printf("Minimum range of double variable: %f\n", DBL_MIN);
    printf("Maximum range of double variable: %f\n", DBL_MAX);
    printf("Minimum range of long double variable: %lf\n", LDBL_MIN);
    printf("Maximum range of long double variable: %lf\n", LDBL_MAX);
    return 0;
}
Was it helpful?

Solution

#include <stdio.h>

main()
{
    float fl, fltest, last;
    double dbl, dbltest, dblast;

    fl = 0.0;
    fltest = 0.0;
    while (fl == 0.0) {
        last = fltest;
        fltest = fltest + 1111e28;
        fl = (fl + fltest) - fltest;
    }
    printf("Maximum range of float variable: %e\n", last);

    dbl = 0.0;
    dbltest = 0.0;
    while (dbl == 0.0) {
        dblast = dbltest;
        dbltest = dbltest + 1111e297;
        dbl = (dbl + dbltest) - dbltest;
    }
    printf("Maximum range of double variable: %e\n", dblast);
    return 0;
}

OTHER TIPS

I did the same exercise these days. I managed to compute the sizes of floats and doubles on my machine assuming 2-complement and IEEE floating point (single and double precision).

I would appreciate any feedback, in particular about the computation of the floating point ranges.

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <float.h>
#include <math.h>

int main(int argc, char** argv) {

    printf("-----------Limits Header-----------\n");

    printf("CHAR_BIT    :   %d\n", CHAR_BIT);
    printf("CHAR_MAX    :   %d\n", CHAR_MAX);
    printf("CHAR_MIN    :   %d\n", CHAR_MIN);
    printf("INT_MAX     :   %d\n", INT_MAX);
    printf("INT_MIN     :   %d\n", INT_MIN);
    printf("LONG_MAX    :   %ld\n", (long) LONG_MAX);
    printf("LONG_MIN    :   %ld\n", (long) LONG_MIN);
    printf("SCHAR_MAX   :   %d\n", SCHAR_MAX);
    printf("SCHAR_MIN   :   %d\n", SCHAR_MIN);
    printf("SHRT_MAX    :   %d\n", SHRT_MAX);
    printf("SHRT_MIN    :   %d\n", SHRT_MIN);
    printf("UCHAR_MAX   :   %d\n", UCHAR_MAX);
    printf("UINT_MAX    :   %u\n", (unsigned int) UINT_MAX);
    printf("ULONG_MAX   :   %lu\n", (unsigned long) ULONG_MAX);
    printf("USHRT_MAX   :   %d\n", (unsigned short) USHRT_MAX);
    printf("FLT_MAX     :   %g\n", (float) FLT_MAX);
    printf("-FLT_MAX    :   %g\n", (float) -FLT_MAX);
    printf("FLT_MIN     :   %g\n", (float) FLT_MIN);
    printf("-FLT_MIN    :   %g\n", (float) -FLT_MIN);
    printf("DBL_MAX     :   %g\n", (double) DBL_MAX);
    printf("-DBL_MAX    :   %g\n", (double) -DBL_MAX);
    printf("DBL_MIN     :   %g\n", (double) DBL_MIN);
    printf("-DBL_MIN    :   %g\n", (double) -DBL_MIN);

    printf("\n");
    printf("--------Assuming 2-complement--------\n");
    printf("-----------Computed limits-----------\n");

    char c = 1;
    while (c > 0)
        c *= 2;
    c--;
    printf("Char max    :   %d\n", c);

    c = 1;
    while (c > 0)
        c *= 2;
    printf("Char min    :   %d\n", c);

    int i = 1;
    while (i > 0)
        i *= 2;
    i--;
    printf("Int max     :   %d\n", i);

    i = 1;
    while (i > 0)
        i *= 2;
    printf("Int min     :   %d\n", i);

    long l = 1;
    while (l > 0)
        l *= 2;
    l--;
    printf("Long max    :   %ld\n", l);

    l = 1;
    while (l > 0)
        l *= 2;
    printf("Long min    :   %ld\n", l);

    signed char sc = 1;
    while (sc > 0)
        sc *= 2;
    sc--;
    printf("Sig Char max:   %d\n", sc);

    sc = 1;
    while (sc > 0)
        sc *= 2;
    printf("Sig Char min:   %d\n", sc);

    short si = 1;
    while (si > 0)
        si *= 2;
    si--;
    printf("Sig Int max :   %d\n", si);

    si = 1;
    while (si > 0)
        si *= 2;
    printf("Sig Int min :   %d\n", si);

    unsigned char uc = 1;
    while (uc > 0)
        uc *= 2;
    uc--;
    printf("U Char max  :   %d\n", uc);

    unsigned int ui = 1;
    while (ui > 0)
        ui *= 2;
    ui--;
    printf("U Int max   :   %u\n", ui);

    unsigned long ul = 1;
    while (ul > 0)
        ul *= 2;
    ul--;
    printf("U Long max  :   %lu\n", ul);

    unsigned short us = 1;
    while (us > 0)
        us *= 2;
    us--;
    printf("U Short max :  %u\n", us);

    union {
        int i;
        float f;
    } uf;
    float f;
    for (f = 1; f < INFINITY; uf.f = f, f *= 1e1);
    for (i = 2, f = uf.f; f * i < INFINITY; uf.f = f * i, i++);
    uf.i = uf.i | 0x7FFFFFu; // Mantissa for float is 23 bit on my machine
    printf("FLT max     :   %g (float)\n", uf.f);
    printf("-FLT max    :   %g (float)\n", -uf.f);
    uf.i = uf.i & 0u;
    uf.i = uf.i | 0x7FFFFFu;
    printf("FLT min     :   %g (float)\n", uf.f);
    printf("-FLT min    :   %g (float)\n", -uf.f);

    union {
        long int i;
        double d;
    } ud;
    double d;
    for (d = 1; d < INFINITY; ud.d = d, d *= 1e1);
    for (i = 2, d = ud.d; d * i < INFINITY; ud.d = d * i, i++);
    ud.i = ud.i | 0xFFFFFFFFFFFFFlu; // Mantissa for double is 52 bit on my machine
    printf("DBL max     :   %g (double) \n", ud.d);
    printf("-DBL max    :   %g (double)\n", -ud.d);
    ud.i = ud.i & 0u;
    ud.i = ud.i | 0xFFFFFFFFFFFFFlu;
    printf("DBL min     :   %g (double)\n", ud.d);
    printf("-DBL min    :   %g (double)\n", -ud.d);

    return (EXIT_SUCCESS);
}

first off, it seems you have bugs in the code. to get max, you need

x = 1;
while(x*2>x)x = x*2 + 1;

once fixed that, use the same formula on floating point number.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top