Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ошибка при дебагге, В итоге не проверить программу 
:(
    Опции темы
bncom
Дата 3.12.2008, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 170
Регистрация: 2.11.2005

Репутация: нет
Всего: 1



Здравствуйте!

На по заданию в университете написал программу, которая модерирует операции сложения и умножения чисел с фиксированной точкой при заданной длине разрядной сетки (n=26) и количестве бит, отводимых под дробную часть (q=7). Все операции проводятся с 10СС. 

В программе реализуется:

1) нахождение минимальное (Amin) и максимальное (Amax) значение числа, суммы чисел, произведения чисел. 
2) нахождение значение ширины кванта (D), суммы чисел (Ds), произведения чисел (Dm).
3) нахождения диапазона ошибки сложения при разных способах квантования, диапазон ошибки умножения при разных способах квантования.

В этой части как бы особых проблем не возникло.

Затем по заданию необходимо дополнить программу, теперь необходимо найти экспериментальную веротяность попадания ошибки в i-интвервал и функцию плотности распределения. Вот здесь и возникла проблема, а именно скорее всего с преобразованием типов (тип дабл привожу к типу инт).

При дебаге выскакивает такая ошибка:

Код

Unhandled exception at 0x00411fac in Laba_2.exe: 0xC0000005: Access violation writing location 0x008d0d7c.



Вот сама программа (она длинная, но понятная, везде написаны комментарии):


Код
// Моделирование операций сложения и умножения в формате с фиксированной точкой
// Длина разрядной сетки: n=26
// Кол-во битов, отводимых под дробную часть: q=7

#include "stdafx.h"
//#include <iostream>
//#include <math.h>
//#include <stdlib.h>

#include <cstdlib>
#include <iostream>
#include <cmath>
#include <fstream>
using namespace std;
#define Amax 262143.9921875
#define Amin -262143.9921875

/*************************************/
/* Генератор чисел                   */
/*************************************/

double generator()
{
    // для того, чтобы значения лежали в интервале больше, чем 32767
    int x=(rand()<<15)+rand();
    double y=(double)x;
    // приводим диапозон к нужному нам виду
    y=((y/32768./32758.-0.5)*2)*Amax;
        return y;
}

/*************************************/
/* Проверка ошибки                   */
/*************************************/
// принадлежат ли значения ошибки квантования допустимому значению?
// 1 - принадлежит, 0- не принадлжеит
int checkerror(double E,double Emin,double Emax)
{
    if ((E>Emin)||(E<Emax))
    {
        return 1;
    }
    return 0;
}

/*************************************/
/* Квантование чисел                 */
/*************************************/

int quantovatel(double x,int flag)
// x - входное генерируемое число
// flag - принимает следующие значения:
// 1 - с округлением до нижней границы кванта
// 2 - с округлением до верхней границы кванта
// 3 - с арифметическим округлением
{
    double y=x*128; // по заданию q=7, 2^7=128, передвигаем точку на 7 разрядов вправо
    int z=(int)y; // отброс дробной части (квантование)

    // если число попало на границу кванта
    if ((y-(double)z)==0)
        return z;

    // приводим диапозон к нужному нам виду
    if (y<0)
        z=z-1;
    if(flag==1)
        return z;
    if(flag==2)
        return(z+1);
    if(flag==3)
        if(y-(double)z>=0.5)
            return (z+1);
        else return z;
    return z;
}

/*************************************/
/* Границы ошибки квантования        */
/*************************************/

void setbounds(int flag,double *E_min,double *E_max)
{
    // с округлением до нижней границы кванта
    if (flag==1)
    {    
        *E_max=0.0078125; // delta=2^-q, q=7
        *E_min=0;
    }
    // с округлением до верхней границы кванта
    if (flag==2)
    {
        *E_max=0;
        *E_min=-0.0078125; // delta=2^-q, q=7
    }
    // с арифметическим округлением
    if (flag==3)
    {
        *E_max=0.00390625; // delta=2^-q,
        *E_min=-0.00390625;
    }
}

/*************************************/
/* Суммирование двух чисел           */
/*************************************/

int sum(int a,int b,int *c)
// sum - передает флаг переполнения (0 или 1)
// a и b - входные числа
// c - возвращаемый адрес значения (результат)
{
    // Sa и Sb - знаки чисел a и b соответственно, Sc - знак суммы 
    int Sa=0, Sb=0, Sc=0, flag_per=0;
    // задаем маску для определения переполнения разрядной сетки
    int mask = 0x2000000;  // единица в двадцать шестом разряде
    // если он равен нулю - число положительное, если единице - отрицательное.
    Sa=a&mask;
    Sb=b&mask;
    *c=a+b;
    if (Sa==Sb)
        {
            Sc=*c&mask;
                if (Sb!=Sc)
                    flag_per=1;
        }
        return flag_per;
}

/*************************************/
/* Установка границ для суммирования */
/*************************************/

void setbounds_sum(int flag,double *Ec_min,double *Ec_max)
// Ec - ошибка сумирования
{
    // границы ошибки суммы
    // с округлением до нижней границы кванта
    if(flag==1)
    {
        *Ec_max=0.015625; // delta=2*(2^-q), q=7
        *Ec_min=0; 
    }
    // с округлением до верхней границы кванта
    if(flag==2)
    {
        *Ec_max=0;
        *Ec_min=-0.015625; // delta=2*(2^-q), q=7
    }
    // с арифметическим округлением
    if(flag==3)
    {
        *Ec_max=0.0078125; // delta=2^-q, q=7
        *Ec_min=-0.0078125; 
    }
}

/*************************************/
/* Умножение двух чисел              */
/*************************************/

__int64 mul(int a,int b,__int64 *d)
// a и b - входные числа
// *d - возвращаемый адрес значения (результат)
{
    int Sa=0, Sb=0, Sd=0;
    // Sa и Sb - знаки чисел a и b соответственно, Sd - знак произведения
    if (a<0)
        {
            a=-a;
            Sa=1;
        }
    if (b<0)
        {
            b=-b;
            Sb=1;
        }
    Sd=Sa^Sb; // находим знак произведения 
    // перемножаем абсолютные величины 
    *d= __int64(a)*__int64(b);
    // проверяем знак произведения
    if (Sd==1)
        {
            *d=-*d;
        }
    return 0;
}

/*************************************/
/* Установка границ для произведения */
/*************************************/

void setbounds_mul(int flag,double at,double bt,double*Ed_min,double *Ed_max)
// at и bt - точные значения для первого и второго сомножителя соответственно
// Ed - ошибка произведения
{
    // делаем значения чисел отрицательными, если это надо
    if (at<0) 
        at=-at;
    if (bt<0) 
        bt=-bt;

    // проверяем, было ли квантование до нижней или верхней границы?
    if ((flag==1)||(flag==2))
    {        
        *Ed_max=1./128.*(at+bt)+1./(128.*128.);
        *Ed_min=-*Ed_max;
    }
    // проверяем, было ли арифметическое квантование?
    if (flag==3)
    {
        *Ed_max=1./256.*(at+bt)+1./(128.*128.*4.);
        *Ed_min=-*Ed_max;
    }
}

/***************************************/
/* Задаем единичный интервал в массиве */
/***************************************/

// для суммы
double IntSum(int flag,int size)
{
    double Emin, Emax;

    // с округлением до нижней границы кванта
    if(flag==1)
    {
        Emin=0;
        Emax=2*1/128.0;
    }
    // с округлением до верхней границы кванта
    if(flag==2)
    {
        Emin=-2*1/128.0;
        Emax=0;
    }
    // с арифметическим округлением
    if(flag==3)
    {
        Emin=-1/128.0;
        Emax=1/128.0;
    }
    return (Emax-Emin)/size;
}

// для произведения
double IntMul(int flag,int size)
{
    double Emax, Emin;

    // с округлением до верхней/нижней границы кванта
    if(flag==1 || flag==2)
    {
        Emax=(1/128.0)*pow(2.,18.)+(1/128.0*1/128.0);
        Emin=-Emax;
    }
    // с арифметическим округлением
    if(flag==3)
    {
        Emax=(1/128.0/2.)*pow(2.,18.)+((1/128.0*1/128.0)/4);
        Emin=-Emax;
    }
    return (Emax-Emin)/size;
}

int main()
{
/*************************************/
/* Объявляем необходимые переменные  */
/*************************************/

    int i=0, kv_a=0, kv_b=0, C=0, error=0, flag_sum=0;
    int flag=1; // задаем флаг - способ квантования (изменяем затем на 2 и 3)
    double a=0, b=0, sum_ab=0, mul_ab=0, E_sum=0, E_mul=0, E_a=0, E_b=0, Emin=0, Emax=0; 
    __int64 flag_mul=0, D;

    // для лаб. работы 2
    const int m=40; // количесвто интервалов
    int Msum[m]={0}; // создаем массив для суммы
    int Mmul[m]={0}; // создаем массив для произведения
    double Psum[m]={0}; // создаем массив для экспериментальной вероятности (сложение)
    double Pmul[m]={0}; // создаем массив для экспериментальной вероятности (произведение)
    double Fsum[m]={0}; // создаем массив для плотности (сложение)
    double Fmul[m]={0}; // создаем массив для плотности (произведение)

// пробегаем миллион раз для пущей убедительности 
for (i=0;i<1000000;i++)
{
    a=generator(); // генерируем число А
        if(checkerror(a,Amin,Amax)==0 || checkerror(b,Amin,Amax)==0)
            return -1;

    kv_a=quantovatel(a, flag); // квантуем число А

    // проверяем работу квантователя
    E_a=a-((double)kv_a)/128.;
    setbounds(flag,&Emin,&Emax);
    error=checkerror(E_a,Emin,Emax);

/*************************************/
/* Для числа B                       */
/*************************************/

    b=generator(); // генерируем число В
        if(checkerror(a,Amin,Amax)==0 || checkerror(b,Amin,Amax)==0)
            return -1;

    kv_b=quantovatel(b, flag); // квантуем число В

    // проверяем работу квантователя
    E_b=b-((double)kv_b)/128.;
    setbounds(flag,&Emin,&Emax);
    error=checkerror(E_b,Emin,Emax);
        
/*************************************/
/* Суммирование                      */
/*************************************/

    sum_ab=a+b;
    flag_sum=sum(kv_a,kv_b,&C);

    // находим ошибку суммирования
    E_sum=sum_ab-((double)C)/128.;
    setbounds_sum(flag,&Emin,&Emax);
    error=checkerror(E_sum,Emin,Emax);

    // вычисляем номер интервала, куда попала ошибка
    int iSum=(E_sum-Emin)/IntSum(flag,40);
    Msum[iSum]+1;

/*************************************/
/* Произведение                      */
/*************************************/

    mul_ab=a*b;
    flag_mul=mul(kv_a,kv_b,&D);

    // находим ошибку произведения
    E_mul=mul_ab-((double)mul_ab)/(128.*128.);
    setbounds_mul(flag,a,b,&Emin,&Emax);
    error=checkerror(E_mul,Emin,Emax);

    // вычисляем номер интервала, куда попала ошибка
    int iMul=(E_mul-Emin)/IntMul(flag,40);
    Mmul[iMul]+1;
}
/*************************************/
/* Лаб. работа 2                     */
/*************************************/

    for(int j=0;j<40;j++)
    {
        double delta=((Emax-Emin)/m); // вычисляем ширину каждого разбитого участка
        
        // для суммы считаем вероятность и плотность
        Psum[i]=(double)Msum[i]/(double)1000000; // считаем экспериментальную вероятность попадания в i-интервал
        Fsum[i]=Psum[i]/delta; // считаем функцию плотности распределения вероятности
    
        // для произведения считаем вероятность и плотность
        Pmul[i]=(double)Mmul[i]/(double)1000000; // считаем экспериментальную вероятность попадания в i-интервал
        Fmul[i]=Pmul[i]/delta; // считаем функцию плотности распределения вероятности

        cout<<Mmul[i]<<" ";
        cout<<endl;
    }

    return 0;
}



Помогите, пожалуйста, избавится от ошибки.
Работаю в Visual C++ 2005.
--------------------
"Мы никогда не живем, мы лишь надеемся, что будем жить." Вольтер 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1144 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.