Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 16.02.2025
Сообщений: 6

Результаты суммирования целого и разбитого массивов отличаются

16.02.2025, 19:40. Показов 2326. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В программе 2 цикла. Один "целый" от 0 до максимального значения, второй цикл разбит на 4 части. Почему-то, когда массив равен const size_t arrSize = 50 000 000; результат суммирования "целого" и "разбитого" массива совпадают, что вполне логично.
Но начиная с некоторого значения, например при const size_t arrSize = 120 000 000; результаты получаются разные, хотя массив состоит из целочисленных переменных. Да, из суммы извлекается квадратный корень, но переменные целочисленные, поэтому ошибок округления при суммировании быть не должно.
Система Windows 10, IDE Code Block 20.03, Процессор Е2682V4.
Вопрос: Это моя ошибка в коде, ошибка компилятора или компьютер не исправен?

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <thread>
#include <cmath>
 
int64_t *Array ;
///const size_t arrSize = 300000000; // результат НЕ правильный
const size_t arrSize = 120000000; // результат НЕ правильный
///const size_t arrSize = 50000000; // результат правильный sum1[0]-rez=0
 
const int threadNumber =4; // Количество потоков
///      номер потока, кол-во потоков
void sqsum(int iTread, int iTN, int64_t *arr, int64_t a_size, int64_t *sum)
 {
 int64_t sumf=0;
 for(int64_t i = iTread; i < a_size; i+=iTN)
    {
        arr[i] =i;
        sumf += sqrt((arr[i] + arr[i]));
    }
    sum[iTread]=sumf;
 }
int64_t  sqsum111( int64_t *arr, int64_t a_size)
 {
 int64_t sumf=0;
 for(int64_t i=0; i < a_size; i++)
    {
        arr[i] =i;
        sumf =sumf+ sqrt((arr[i] + arr[i]));
    }
        return sumf;
 }
 
int main()
 {
    system("chcp 1251");
 // заполнение массива Array
    Array = new int64_t[arrSize];
    if(Array == nullptr)
        {
            std::cout << "Incorrect size= "<< arrSize << "\n";
            return 1;
        }
 
 int64_t sum[threadNumber]={0};
 int64_t sum1[threadNumber]={0};
 
 for(size_t i = 0; i < arrSize; ++i)
    {
        *(Array+i)=0;
    };
 int64_t sum_ret= sqsum111( Array,arrSize);
 std::cout << "Результат sum_ret= "<< sum_ret << std::endl ;
 
 sqsum(0,1, Array, arrSize,sum1);
 std::cout << "Результат за целый цикл["<<0<<"] = "<< sum1[0] << std::endl ;
 
 sqsum(0,4, Array, arrSize,sum);
 std::cout << "Сумма sum_func["<<0<<"] = "<< sum[0] << std::endl ;
 sqsum(1,4, Array, arrSize,sum);
 std::cout << "Сумма sum_func["<<1<<"] = "<< sum[1] << std::endl ;
 sqsum(2,4, Array, arrSize,sum);
 std::cout << "Сумма sum_func["<<2<<"] = "<< sum[2] << std::endl ;
 sqsum(3,4, Array, arrSize,sum);
 std::cout << "Сумма sum_func["<<3<<"] = "<< sum[3] << std::endl ;
 
 int64_t rez = 0 ; //для результата
 
 // Завершение
 for (int i=0 ; i<threadNumber ; i++)
    {
        rez += sum[i];
    }
 std::cout << "Сумма циклов по 4 частям = "<< rez << "\n" ;
 std::cout << "Разница результатов = "<<sum1[0]-rez << "\n" ;
 delete[] Array;
 
 return 0;
}
Добавлено через 19 минут
Спасибо большое, что поправили сообщение

Добавлено через 5 секунд
Спасибо большое, что поправили сообщение
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
16.02.2025, 19:40
Ответы с готовыми решениями:

Как целочисленный массив X из n элементов разбить на m фрагментов?
Целочисленный массив X из n элементов разбит на m фрагментов. В целочисленном массиве K из m элементов хранятся длины соответствующих...

Дан массив упорядоченных по возрастанию целых чисел. разработать алгоритм бинарного поиска заданного числа, результат номер искомого числа или 0 если
помогите решить задачу: Дан массив упорядоченных по возрастанию целых чисел. разработать алгоритм бинарного поиска заданного числа,...

Программа котрая ищет дубликаты в целочисленном массиве и если они есть выводит результат на экран
Я не могу понять почему когда присваиваешь элементы одного массива другому элементы второго массива всё равно равны 0 #include...

11
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6088 / 2779 / 1037
Регистрация: 01.06.2021
Сообщений: 10,138
16.02.2025, 19:51
Цитата Сообщение от vasya_sidorov_2 Посмотреть сообщение
#include <thread>
купил лопату, но яму роешь руками?
1
place status here
 Аватар для gunslinger
3185 / 2219 / 640
Регистрация: 20.07.2013
Сообщений: 5,986
16.02.2025, 20:12
Не знаю, что тут за "потоки" и задача в целом, но (частичные суммы не все одинаковые, равны только sum_func[2] и sum_func[3]):
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
//#include <thread>
#include <cmath>
using namespace std;
 
typedef unsigned long int64_t;
 
int64_t *Array ;
//const size_t arrSize = 300000000; // результат правильный
const size_t arrSize = 120000000; // результат правильный
//const size_t arrSize = 50000000; // результат правильный sum1[0]-rez=0
 
const int threadNumber =4; // Количество потоков
///      номер потока, кол-во потоков
void sqsum(int iTread, int iTN, int64_t *arr, int64_t a_size, int64_t *sum)
 {
 int64_t sumf=0;
 for(int64_t i = iTread; i < a_size; i+=iTN)
    {
        arr[i] =i;
        sumf += sqrt(2. * arr[i]);
    }
    sum[iTread]=sumf;
 }
int64_t  sqsum111( int64_t *arr, int64_t a_size)
 {
 int64_t sumf=0;
 for(int64_t i=0; i < a_size; i++)
    {
        arr[i] =i;
        sumf =sumf+ sqrt(2. * arr[i]);
    }
        return sumf;
 }
 
int main()
 {
  //  system("chcp 1251");
 // заполнение массива Array
    Array = new int64_t[arrSize];
    if(Array == NULL)
        {
            std::cout << "Incorrect size= "<< arrSize << "\n";
            return 1;
        }
 
 int64_t sum[threadNumber]={0};
 int64_t sum1[threadNumber]={0};
 
 for(size_t i = 0; i < arrSize; ++i)
    {
        *(Array+i)=0;
    };
 int64_t sum_ret= sqsum111( Array,arrSize);
 std::cout << "sum_ret= "<< sum_ret << std::endl ;
 
 sqsum(0,1, Array, arrSize,sum1);
 std::cout << "sum1["<<0<<"] = "<< sum1[0] << std::endl ;
 
 sqsum(0,4, Array, arrSize,sum);
 std::cout << "sum_func["<<0<<"] = "<< sum[0] << std::endl ;
 sqsum(1,4, Array, arrSize,sum);
 std::cout << "sum_func["<<1<<"] = "<< sum[1] << std::endl ;
 sqsum(2,4, Array, arrSize,sum);
 std::cout << "sum_func["<<2<<"] = "<< sum[2] << std::endl ;
 sqsum(3,4, Array, arrSize,sum);
 std::cout << "sum_func["<<3<<"] = "<< sum[3] << std::endl ;
 
 int64_t rez = 0 ; //для результата
 
 // Завершение
 for (int i=0 ; i<threadNumber ; i++)
    {
        rez += sum[i];
    }
 std::cout << "rez = "<< rez << "\n" ;
 std::cout << "sum1[0]-rez = "<<sum1[0]-rez << "\n" ;
 delete[] Array;
 std::system("pause");
 return 0;
}
Для arrSize = 120000000:
Code
1
2
3
4
5
6
7
8
sum_ret= 2344084856
sum1[0] = 2344084856
sum_func[0] = 586013468
sum_func[1] = 586021214
sum_func[2] = 586025087
sum_func[3] = 586025087
rez = 2344084856
sum1[0]-rez = 0
Для arrSize = 300000000:
Code
1
2
3
4
5
6
7
8
sum_ret= 2566761089
sum1[0] = 2566761089
sum_func[0] = 641678025
sum_func[1] = 641690272
sum_func[2] = 641696396
sum_func[3] = 641696396
rez = 2566761089
sum1[0]-rez = 0
Для arrSize = 50000000:
Code
1
2
3
4
5
6
7
8
sum_ret= 2595848208
sum1[0] = 2595848208
sum_func[0] = 1722698876
sum_func[1] = 1722703876
sum_func[2] = 1722706376
sum_func[3] = 1722706376
rez = 2595848208
sum1[0]-rez = 0
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12919 / 6787 / 1817
Регистрация: 18.10.2014
Сообщений: 17,169
16.02.2025, 20:15
Лучший ответ Сообщение было отмечено vasya_sidorov_2 как решение

Решение

Цитата Сообщение от vasya_sidorov_2 Посмотреть сообщение
Вопрос: Это моя ошибка в коде, ошибка компилятора или компьютер не исправен?
Это результат разного округления при приведении от double к int64_t после сложения. В выражении

C++
1
sumf = sumf+ sqrt(arr[i] + arr[i]);
сложение выполняется в рамках типа double, а затем результат приводится к типу int64_t. При "перетасовке" слагаемых это будет приводить к отличиям в финальном результате. Если вы хотите избежать этого эффекта, то приводить результат sqrt к целому нужно до сложения. То есть везде сделать:

C++
1
(int64_t) sqrt(arr[i] + arr[i])
и различия тут же пропадут.
3
place status here
 Аватар для gunslinger
3185 / 2219 / 640
Регистрация: 20.07.2013
Сообщений: 5,986
16.02.2025, 20:28
В моем посте нужно в typedef заменить unsigned long на unsigned long long и увеличить размер стека (если необходимо).
А вообще да, странно выглядит попытка "перекинуть" вычисления на ядра-потоки путем простого ввода переменной.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12919 / 6787 / 1817
Регистрация: 18.10.2014
Сообщений: 17,169
16.02.2025, 21:16
Цитата Сообщение от vasya_sidorov_2 Посмотреть сообщение
Вопрос: Это моя ошибка в коде,
Вот, например, некий набор "достаточно больших" чисел, на котором будет проявляться это явление

C++
1
2
3
4
5
6
7
8
9
10
11
  const std::int64_t BASE = 549'992'868'348;
  const std::int64_t ADD = 74'164'020;
 
  std::int64_t a = BASE;
  a += std::sqrt(ADD * 2);
  std::cout << a << std::endl;
 
  std::int64_t b = BASE / 4;
  b += std::sqrt(ADD * 2);
  b += BASE - BASE / 4;
  std::cout << b << std::endl;
Эти вычисления, следуя логике вашего исходного варианта, должны выдавать одинаковые результаты. Однако в реальности мы получаем

Code
1
2
549992880527
549992880526
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Это результат разного округления при приведении от double к int64_t после сложения.
Это мое утверждение не совсем верно. Источником проблемы является скорее округление в рамках типа double при выполнении вычислений с большими числами, когда точности типа double становится уже недостаточно для правильного представления даже целой части результата.

Приведенный пример это демонстрирует. Результат std::sqrt(ADD * 2) равен 12178.999959. Однако сумма BASE + 12178.999959 дает 549992880527.000000, т.е. происходит округление в большую сторону до следующего целого уже в рамках double. Сумма же BASE / 4 + 12178.999959 дает 137498229265.999969, т.е. не вызывает округления вверх до следующего целого. Именно это отличие и приводит к разнице в результатах.
2
0 / 0 / 0
Регистрация: 16.02.2025
Сообщений: 6
17.02.2025, 11:28  [ТС]
Изучаю паралельное программирование, написал программу-тест на 4 потока, а так как современные процессоры очень быстрые, пришлось делать большой массив и извлекать корень из суммы. При этом был уверен, что корень из целого будет целым числом. А оказалось, что происходит приведение к вещественному типу. Век живи век учись...
Приведение типа по умолчанию - это зло.
А программа выглядит странно, потому что задавая вопрос вырвал нужный кусок убрав все лишнее.

Добавлено через 3 минуты
Всем ответившим по делу Большое спасибо. Даже не ожидал, что корень из целого числа приводится в вещественному типу.
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6088 / 2779 / 1037
Регистрация: 01.06.2021
Сообщений: 10,138
17.02.2025, 11:50
Цитата Сообщение от vasya_sidorov_2 Посмотреть сообщение
Изучаю паралельное программирование, написал программу-тест на 4 потока, а так как современные процессоры очень быстрые, пришлось делать большой массив и извлекать корень из суммы.
у тебя вот такая многопоточность Прикольные видео

Добавлено через 1 минуту
Цитата Сообщение от vasya_sidorov_2 Посмотреть сообщение
При этом был уверен, что корень из целого будет целым числом.
есть и такая функция, но называется она isqrt (integer square root).
1
Заблокирован
17.02.2025, 17:42
Цитата Сообщение от Royal_X Посмотреть сообщение
есть и такая функция, но называется она isqrt
А где она есть?
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6088 / 2779 / 1037
Регистрация: 01.06.2021
Сообщений: 10,138
17.02.2025, 17:44
Цитата Сообщение от SmallEvil Посмотреть сообщение
А где она есть?
например, здесь https://github.com/RoyalXXX/bigint
0
Заблокирован
17.02.2025, 17:56
Кликните здесь для просмотра всего текста


0
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,678
18.02.2025, 11:56
Цитата Сообщение от Royal_X Посмотреть сообщение
например, здесь
ждем в c++28 или 30? ))))
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
18.02.2025, 11:56
Помогаю со студенческими работами здесь

Разбить строку типа AnsiString на массив целых чисел
Имеется строка типа AnsiString: 12 35 1 16 0 12 3 412 Есть ли у данного типа данных какая-нибуть функция, что позволит разбить строку...

Разный результат при суммировании элементов массива
double a={0.50,0.51,0.52,0.53,0.54,0.55,0.56};// значеиня х double a2; double a3; double a4; double...

Как разбить строку на символы и поместить в целочисленный массив?
Нужно ввести число в string далее разбить строку на отдельные символы и поместить каждый символ в отдельными элемент целочисленного...

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

Каждый отрицательный элемент массива заменить результатом его целочисленного деления на 3
10. Ввести одномерный массив из элементов. Каждый отрицательный элемент в массиве заменить результатом его целочисленного деления на 3....


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru