1 Востаннє редагувалося FakiNyan (04.12.2014 11:54:47)

Тема: Проблема з переведенням 80-бітного числа в double

Хай. Декілька тижднів тому я писав лабу ,котра переводить double у 80-бітне число, котре треба, аби використовувати його в FPU.
Так от, я тестував це на числах типу 154.354 і т.д.
А зараз ввожу ось таке число

-17.27800688

Перевожу його спочатку в 80-бітне, після цього пробую перевести назад в double, але тоді в мене виходить ось таке

-17.278

Я спробував інші циферки, щоб не було нулів, і побачив, що число округлюється до 4 знака після коми.
Це так і має бути, чи я щось зробив не так?
от вам увесь кід, якщо тре

#include <iostream>
#include <cstdlib>
#include <vector>

using namespace std;

void toBinary(int integer, vector<int>* vector)
{    
    integer = abs(integer);
    for (int i = 0; integer > 0; i++)
    {
        vector->insert(vector->begin(), integer % 2);
        integer /= 2;
    }
}

int toInt(vector<int>* vec)
{
    int result = 0;
    for (int i = vec->size()-1; i >=0; i--)
    {
        if (vec->at(vec->size()-1-i))
        {
            result += pow(2, i);
        }
    }
    return result;
}

double toDouble(vector<int>* vec)
{
    double result=0;
    for (int i = vec->size()-1; i >= 0; i--)
    {
        result += vec->at(i);
        result /= 2;
    }
    return result;
}

double Binary80ToDouble(vector<int> vec)
{
    vector<int> integerPart;
    vector<int> doublePart;
    vector<int> exponenta(15);
    int exp = 0;

    for (int i = 0; i < 15; i++)
    {
        exponenta[i] = vec[i + 1];
    }

    exp = toInt(&exponenta);
    exp -= 16383;

    vector<int> temp(64);
    int n = 0;
    for (int i = 0; i < 63; i++)
    {
        n++;
        temp[i] = vec[i + 17];
    }

    integerPart.push_back(1);
    for (int i = 0; i < exp; i++)
    {
        integerPart.push_back(temp[i]);
    }

    for (int i = integerPart.size()-1; i < temp.size(); i++)
    {
        doublePart.push_back(temp[i]);
    }

    int integer = toInt(&integerPart);
    double fl = toDouble(&doublePart);

    //cout << endl << "integer part: " << integer << endl << "double part: " << fl << endl;

    fl += integer;

    //cout << "full number: " << fl << endl;
    if (vec[0] == 1)
    {
        fl *= -1;
    }
    return fl;
}

vector<int> doubleToBinary80(double number)
{
    int integer = (int)number;
    int exp;
    double fl = number - integer;
    vector<int> integerPart;
    vector<int> doublePart;
    vector<int> exponenta;
    vector<int> fullBinaryNumber(80);

    toBinary(integer, &integerPart);

    if (integerPart.size() > 1)
    {
        exp = integerPart.size() - 1;
    }

    exp += 16383;

    integer = abs(integer);
    fl = abs(fl);

    toBinary(exp, &exponenta);

    for (int i = 0; i < 80 - 16 - integerPart.size(); i++)
    {
        fl *= 2;
        if (fl >= 1)
        {
            doublePart.push_back(1);
            fl -= 1;
        }
        else
        {
            doublePart.push_back(0);
        }
        if (fl == 0) break;
    }

    if (number > 0)
    {
        fullBinaryNumber[0] = 0;
    }
    else
    {
        fullBinaryNumber[0] = 1;
    }

    for (int i = 0; i < exponenta.size(); i++)
    {
        fullBinaryNumber[i + 1] = exponenta[i];
    }
    fullBinaryNumber[17] = 1;
    for (int i = 0; i < integerPart.size(); i++)
    {
        fullBinaryNumber[i + 16] = integerPart[i];
    }

    for (int i = 0; i < doublePart.size(); i++)
    {
        int temp = 16 + integerPart.size() + i;
        fullBinaryNumber[temp] = doublePart[i];
    }

    for each(auto var in integerPart)
    {
        cout << var;
    }
    cout << endl;
    for each(auto var in doublePart)
    {
        cout << var;
    }
    cout << endl;

    return fullBinaryNumber;
}

int main()
{

    vector<int> fullBinaryNumber = doubleToBinary80(-17.27800688);
    int del = 0;
    for each (int var in fullBinaryNumber)
    {
        if (del % 4 == 0) cout << " ";
        del++;
        cout << var;
    }
    cout << endl;
    double number = Binary80ToDouble(fullBinaryNumber);
    cout << number;


    /*double fl = 4;
    int in = 3;
    __asm {
            fld fl
            fild in
            fdiv st(0), st(1)
            fst fl
    }

    cout << fl;*/


    system("pause>>void");
}

2

Re: Проблема з переведенням 80-бітного числа в double

Ваш код важко читати: багато сталих посеред тексту, натомість повинні бути іменовані сталі - const int .... Також варто спробувати розбити велику функцію на менші з врозумливими іменами. Дякую.

З.І. Поки це робитимете, то й помилку можете знайти:)

3

Re: Проблема з переведенням 80-бітного числа в double

Yola написав:

Ваш код важко читати: багато сталих посеред тексту, натомість повинні бути іменовані сталі - const int

А які сталі вас засмучують? Я там не бачу жодної, призначення якої було б мені ну зовсім не зрозуміло. Проблема сталих в коді - більше в тому, що вони мають тенденцію рано чи пізно змінюватися, а не в читаності. І тоді константи всіх рятують.

4

Re: Проблема з переведенням 80-бітного числа в double

16383?
80 - 16? що тут 16? це місце для чого?

5

Re: Проблема з переведенням 80-бітного числа в double

16383 == 0x3FFF - тобто 14 одиничок, хіба не очевидно?
16 - місце для... гм... а ви взагалі в курсі питання? Чи збиралися спершу глючний код читати, а потім завдання?

Подякували: FakiNyan1

6

Re: Проблема з переведенням 80-бітного числа в double

Ні, не очевидно.
Завдання, хто взагалі читає завдання?

Код може бути хоч і глючним, але зрозумілим.

7

Re: Проблема з переведенням 80-бітного числа в double

Yola написав:

Ні, не очевидно.
Завдання, хто взагалі читає завдання?

Код може бути хоч і глючним, але зрозумілим.

Ну це ж задача не тривіальна, майбуть. Тому не розуміючи самого алгоритму переведення числа - ви і код не зрозумієте, це ж очевидно.