Форум программистов, компьютерный форум CyberForum.ru

Нахождение среднего арифметического без переполнения - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.83
vampik
0 / 0 / 0
Регистрация: 30.03.2011
Сообщений: 41
20.04.2012, 16:43     Нахождение среднего арифметического без переполнения #1
Задача найти среднее арифметическое целых чисел (int).
Если просто складывать их и потом делить на количество происходит переполнение...
может кто подскажет алгоритм как это осуществить без переполнения а то я никак допереть не могу...
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Heretiqu3
10 / 10 / 2
Регистрация: 19.04.2012
Сообщений: 20
20.04.2012, 16:44     Нахождение среднего арифметического без переполнения #2
Цитата Сообщение от vampik Посмотреть сообщение
Задача найти среднее арифметическое целых чисел (int).
Если просто складывать их и потом делить на количество происходит переполнение...
может кто подскажет алгоритм как это осуществить без переполнения а то я никак допереть не могу...
Код выложите свой, где не работает.
vampik
0 / 0 / 0
Регистрация: 30.03.2011
Сообщений: 41
20.04.2012, 16:51  [ТС]     Нахождение среднего арифметического без переполнения #3
Цитата Сообщение от Heretiqu3 Посмотреть сообщение
Код выложите свой, где не работает.
Есть массив из 1000 и более элементов нужно найти среднее...
Проект большой не вижу смысла выкладывать...
но факт в том что после того как я складываю некоторое количество элементов из массивов они выходят за пределы (сумма становится слишком большой)... поэтому результаты получаются неадекватными..
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
20.04.2012, 16:59     Нахождение среднего арифметического без переполнения #4
Складывайте их (значения) в переменную типа double, а то и long double, если всё так серьёзно. Целое число в качестве среднего арифметического - всё равно редкость...
vampik
0 / 0 / 0
Регистрация: 30.03.2011
Сообщений: 41
20.04.2012, 17:03  [ТС]     Нахождение среднего арифметического без переполнения #5
Цитата Сообщение от easybudda Посмотреть сообщение
Складывайте их (значения) в переменную типа double, а то и long double, если всё так серьёзно. Целое число в качестве среднего арифметического - всё равно редкость...
У меня пока что у массивов такая размерность...
а потом может стать и еще больше...
просто хотелось бы вообще быть независимым от переполнения...может кто-то какой-то алгоритм а то условно будет у меня 10000 элементов с большим значением... и там уже никакие типы не помогут...
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.04.2012, 17:23     Нахождение среднего арифметического без переполнения #6
Цитата Сообщение от vampik Посмотреть сообщение
Задача найти среднее арифметическое целых чисел (int).
Если просто складывать их и потом делить на количество происходит переполнение...
может кто подскажет алгоритм как это осуществить без переполнения а то я никак допереть не могу...
А сколько у тебя целых, какого они типа и какого реального диапазона? Если signed showt int складывать через преобразование в signed long int, то переполнение гарантировано не наступит при сложении 65535-ти слагаемых, так как удвоение разрядности расширяет диапазон квадратично, а удвоение диапазона происходит при повышении разрядности всегда на 1 бит. Мало? Эйси. Сложи по частям, каждую из сумм раздели, а потом найди средневзвешенное от этих средних. У тебя уже signed long int? Ну тогда складывай в __int64 (он же hyper), влезет больше 4-х миллиардов слагаемых. Уже hyper? Создай 128-ми битный тип, операторы для его сложения и деления и приведения hyper к нему и работай в этом типе.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
20.04.2012, 17:27     Нахождение среднего арифметического без переполнения #7
Среднее арифметическое: http://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{{x}_{1} + {x}_{2} + ... + {x}_{n}}{n} = \frac{{x}_{1}}{n} + \frac{{x}_{2}}{n} + ... + \frac{{x}_{n}}{n}
Думаю идея понятна.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
 
int main() {
  const int size = 10;
  int a[ size  ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  
  double b = 0;
  
  for ( int i = 0; i < 10; i++ )
     b += static_cast< double >( a[ i ] ) / size;
     
  std::cout << b << std::endl;
  
  return 0;
}
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.04.2012, 17:29     Нахождение среднего арифметического без переполнения #8
Цитата Сообщение от Toshkarik Посмотреть сообщение
int a[ size *] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Это даже байт переполнить не может.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
20.04.2012, 17:30     Нахождение среднего арифметического без переполнения #9
taras atavin, причем здесь это? Мы не складываем все переменные в одну, поэтому переполнения быть не может, так как среднее арифметическое максимум будет равно наибольшему элементу.
ProNoooob
71 / 71 / 6
Регистрация: 14.10.2009
Сообщений: 121
20.04.2012, 17:32     Нахождение среднего арифметического без переполнения #10
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "windows.h"
#include <stdlib.h>
#include <stdio.h>
 
double Hello(unsigned int *begin, unsigned int *end, int size)
{
    if((begin + 1) == end) //конец массива
        return (double)(*begin + *(begin + 1))/size;
    else if(begin + 2 == end) //конец массива, но в конце целых три эелемента
        return (double)(*begin + *(begin + 1) + *(begin + 2))/size;
    else                     // вычисляем потихоньку
        return (double)(*begin + *(begin + 1))/size + (double)Hello(begin + 2, end, size);
}
 
int main()
{
    unsigned int X[1000];
    unsigned int i;
    double result;
 
    srand(GetTickCount());
    for(i = 0; i < 1000; i++)
    {
        X[i] = rand() % 100;
    }
 
    result = Hello(X, &X[999], 1000);
 
    return 0;
}
вроде работает. Простая задачка.

А вообще если есть возможность, то такую математику лучше на лиспе писать.
Большинство его реализаций поддерживают длинную арифметику.
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.04.2012, 17:34     Нахождение среднего арифметического без переполнения #11
Цитата Сообщение от Toshkarik Посмотреть сообщение
taras atavin, причем здесь это? Мы не складываем все переменные в одну.
Попытка деления сразу при работе в целом типе может приводить к нулевому результату, если количество усредняемых данных больше самих данных, дробные операции относительно дорогие, особенно деление, а если делить в конце, то он и мантиссу double побоится переполнить, у тебя же простейший случай, где переполнение и так не грозит.
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
20.04.2012, 17:36     Нахождение среднего арифметического без переполнения #12
Цитата Сообщение от taras atavin Посмотреть сообщение
Попытка деления сразу при работе в целом типе может приводить к нулевому результату, если количество усредняемых данных больше самих данных.
Вообще из этого ничего не понял, переформулируйте пожалуйста.
Nekto
342 / 287 / 10
Регистрация: 23.03.2012
Сообщений: 838
20.04.2012, 17:42     Нахождение среднего арифметического без переполнения #13
C++
1
2
3
4
5
6
7
8
9
10
11
12
long double f(int * a, int size)
{
 int s=0;
 int ostatok=0;
 for (int i=0;i<size;i++)
  {
   ostatok+=a[i];
   s+=ostatok/size;
   ostatok=ostatok%size;
  }
 return s+1.0*ostatok/size;
}
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,898
Завершенные тесты: 1
20.04.2012, 18:05     Нахождение среднего арифметического без переполнения #14
C
1
2
3
4
5
6
7
8
9
10
11
12
13
int Mean(int *data, unsigned int size)  /*Среднее арифметическое с округлением вниз*/
{
    int mean = 0, accum = 0, delta;
    unsigned int i = 0;
    for(; i<size; ++i)
    {
        accum += data[i];
        delta = accum / size;
        mean += delta;
        accum -= delta*size;
    }
    return mean;
}
saserlend
10 / 10 / 1
Регистрация: 25.11.2011
Сообщений: 138
20.04.2012, 19:10     Нахождение среднего арифметического без переполнения #15
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <math.h>
void main()
{
int a, b=0,c=0;
double d;
printf("chislo, 0 vihod\t\n");
do
{scanf("%d",&a);
c++;
d=b+a/c;
b+=a;
printf("shag %d result = %f\n", c, d); 
 }
while (a!=);
}
Не знаю может где ошибся, с телефона написал

Добавлено через 14 минут
while (a!=0); и d=(b+a)/c
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.04.2012, 19:40     Нахождение среднего арифметического без переполнения #16
Цитата Сообщение от Toshkarik Посмотреть сообщение
Вообще из этого ничего не понял, переформулируйте пожалуйста.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <iosream.h>
#include <math.h>
void main()
{
 int a[20]={1, 2, 4, 5, 7, 5, 8, 4, 3, 2, 9, 5, 4, 6, 2, 7, 4, 5, 1, 3};
 int i, s1,s2;
 for (i=0, s1=0, s2=0; i<20; ++i)
 {
  s1+=a[i]/20;
  s2+=a[i];
 }
 s2/=a20;
 std::cout<<"s1="<<s1<<", s2="<<s2<<endl;
 return 0;
}
выведет:
s1=0, s2=4
.
thick_int
Заблокирован
20.04.2012, 19:57     Нахождение среднего арифметического без переполнения #17
А у меня эта задача ассоциируется вот с таким кодом:
Исходный массив должен быть дополнен нулями так, чтобы общее число элементов в этом новом массиве являлось некоторой степенью двойки.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
double average(int const arr[], size_t arrsize)
{
    int total = 0;
    try
    {
        for (size_t count(0); count < arrsize; ++count)
        {
            total += arr[count];
        }
    }
    catch (overflow_error &e)
    {
        return (average(arr, arrsize >> 2) + average(arr + (arrsize >> 2), arrsize >> 2)) / static_cast<double>(2);
    }
    return static_cast<double>(total) / static_cast<double>(arrsize);
}
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
20.04.2012, 19:59     Нахождение среднего арифметического без переполнения #18
taras atavin, не потому ли у Toshkarik сделано
Цитата Сообщение от Toshkarik Посмотреть сообщение
b += static_cast< double >( a[ i ] ) / size;
? И получается всё, как надо, а так-то любую идею можно забыдлокодить до полной непригодности...
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
20.04.2012, 20:00     Нахождение среднего арифметического без переполнения #19
Вы видели вообще мой код? Например что тип переменной double? И что там каст к double? Тем более я просто показал, что можно делить каждую переменную в отдельности для избежания переполнения. Если без каста, то тут уже достаточно привели примеров, использующий данный метод. Единственный пример показался не правильным из последнего поста предыдущей страницы, так как рекурсии нужно избегать при обработке большого количества данных.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.04.2012, 20:02     Нахождение среднего арифметического без переполнения
Еще ссылки по теме:

C++ Реализовать нахождение среднего арифметического элементов массива
C++ Нахождение среднего арифметического трех целых чисел или суммы двух вещественных
Нахождение среднего арифметического без учета максимального элемента C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
taras atavin
Ушёл с форума.
 Аватар для taras atavin
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
20.04.2012, 20:02     Нахождение среднего арифметического без переполнения #20
Цитата Сообщение от taras atavin Посмотреть сообщение
s2/=a20;
То есть
C++
1
s2/=20;
Добавлено через 1 минуту
Цитата Сообщение от easybudda Посмотреть сообщение
не потому ли у Toshkarik сделано
дробные операции дороже целых равно разрядности.
Yandex
Объявления
20.04.2012, 20:02     Нахождение среднего арифметического без переполнения
Ответ Создать тему
Опции темы

Текущее время: 16:38. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru