Как определить диапазоны типов с плавающей точкой, используя прямые вычисления? - PullRequest
7 голосов
/ 29 ноября 2011

Я пытаюсь решить упражнение 2-1 из "Языка программирования C", 2-е издание, которое просит:

"Напишите программу для определения диапазонов переменных типа char, short, int и long, как со знаком, так и без знака, путем печати соответствующих значений из стандартных заголовков и путем прямого вычисления. Сложнее, если вы их вычисляете: определите диапазоны различные типы с плавающей точкой. "

Мне удалось определить диапазоны всех типов, кроме плавающих, как с использованием минимальных и максимальных значений из стандартных заголовков, так и путем прямых вычислений.

Как определить диапазоны типов с плавающей точкой, используя прямые вычисления?

#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;
}

Ответы [ 3 ]

4 голосов
/ 01 декабря 2011
#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;
}
1 голос
/ 03 августа 2015

Я делал то же самое в эти дни.Мне удалось вычислить размеры чисел с плавающей запятой и двойных чисел на моей машине, предполагая 2-комплемент и IEEE с плавающей запятой (одинарная и двойная точность).диапазоны с плавающей запятой.

#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);
}
0 голосов
/ 29 ноября 2011

во-первых, кажется, у вас есть ошибки в коде.чтобы получить максимум, вам нужно

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

после исправления, используйте ту же формулу для числа с плавающей точкой.

...