Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.89/19: Рейтинг темы: голосов - 19, средняя оценка - 4.89
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445

Умножение и деление

08.07.2013, 17:36. Показов 3962. Ответов 39
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Представьте себе числовой массив первым элементом равным begin. Если далее к нему мы будем прибавлять step пока не достигнем end то сформируем массив. Таким образом размер такого массива будет вычисляться по формуле
C++
1
size = static_cast<size_t>((end - begin) / step) + 1;
а последний элемент можно будет найти по формуле
C++
1
last = min + step * (size - 1);
Всё бы ничего но иногда отрезок делится на step целое число раз начинаются проблемы: из-за погрешности операций над вещественными числами в каком-то бородатом знаке после запятой результат деления оказывается чуть меньше целого числа, т. е., например, если begin = 1.0, end = 3.0, step = 1.0, при делении может оказаться что (end - begin) / step = 1.99999999999, в результате мы получим size = 2, хотя в массиве должны быть 1.0, 2.0 и 3.0. Безграмотное решение:
C++
1
size = static_cast<size_t>((end - begin) / step + 1e-8) + 1;
Вопрос к знатокам всяких там <cfloat> и <limits>: как это сделать грамотно?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.07.2013, 17:36
Ответы с готовыми решениями:

Вычитание, умножение, деление столбиком
дано мне в классе 2 числа представленные в виде массивов. вот..для них у меня должны быть перегрузки операций сложения,вычитания,умножения...

Чем заменить умножение и деление?
Пожалуйста, подскажите, как выполнить следующие действия в С++, не используя умножениe и деление. Напишите программу, вычисляющую...

Умножение и деление целого числа
1. Напишите программу, в которой умножение и деление целого числа на {2}^{n} реализуется при помощи логических сдвигов.

39
14 / 9 / 0
Регистрация: 12.07.2012
Сообщений: 82
08.07.2013, 17:59
Но почему не используется целочисленный тип?
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
08.07.2013, 18:02  [ТС]
какой целочисленный тип? о чем вы? Мне нужно описать произвольный интервал данных. от e до pi к примеру... с шагом log(0.1)
0
0 / 0 / 1
Регистрация: 08.07.2013
Сообщений: 19
08.07.2013, 18:05
Цитата Сообщение от CEBEP Посмотреть сообщение
...
C++
1
size = static_cast<size_t>((end - begin) / step) + 1;
...
C++
1
size = static_cast<size_t>((end - begin) / step + 1e-8) + 1;
Вопрос к знатокам всяких там <cfloat> и <limits>: как это сделать грамотно?
C++
1
size = (size_t)((end - begin) / step) + 1;
Кто же тебя надоумил кастовать по статик? Простое преобразование должно решить твою проблему.
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
08.07.2013, 18:11  [ТС]
Цитата Сообщение от Avyyakta Посмотреть сообщение
Простое преобразование должно решить твою проблему.
типа (int)? чем от отличается? в с++ он просто вызывает последовательно несколько кастов.
0
154 / 110 / 9
Регистрация: 12.06.2013
Сообщений: 168
08.07.2013, 18:12
Цитата Сообщение от Avyyakta Посмотреть сообщение
Кто же тебя надоумил кастовать по статик? Простое преобразование должно решить твою проблему.
Гражданин, пройдите в сторону чистого С. В топике про С++ вам не место.
0
0 / 0 / 1
Регистрация: 08.07.2013
Сообщений: 19
08.07.2013, 18:33
Цитата Сообщение от zenw Посмотреть сообщение
Гражданин, пройдите в сторону чистого С. В топике про С++ вам не место.
Отчего же?
Просто парень не знает, что статик каст не преобразует данные.
Кастование создано для того чтобы изменять области видимости компилятором, а не для преобразования данных.
И size_t это вовсе не int (по крайней мере в C++), хотя также целочисленно.
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
08.07.2013, 19:04  [ТС]
Цитата Сообщение от Avyyakta Посмотреть сообщение
Кастование создано для того чтобы изменять области видимости компилятором
действительно не знаю. Чем это отличается от приведения типов?

Добавлено через 1 минуту
обычно касты используют при работе с указателями, я думал тут дело в том, что при работе с переменными отличие кастов от приведения типов в стиле си не существенно. однако, я много раз видел, например в qt, чтобы там приводили именно переменные к нужному типу с помощью кастов

Добавлено через 2 минуты
проверил, если написать
C
1
s = (size_t)((end - begin) / step) + 1;
то проблема не решается.
0
0 / 0 / 1
Регистрация: 08.07.2013
Сообщений: 19
08.07.2013, 19:14
Цитата Сообщение от CEBEP Посмотреть сообщение
действительно не знаю. Чем это отличается от приведения типов? насчет int - просто был не уверен что в си есть size_t. Везде где я работал он просто unsigned int...
Все зависит от компилятора... В моем любимои GNU С++ ver. 4 size_t это unsigned long.
Цитата Сообщение от CEBEP Посмотреть сообщение
обычно касты используют при работе с указателями, я думал тут дело в том, что при работе с переменными отличие кастов от приведения типов в стиле си не существенно. однако, я много раз видел, например в qt, чтобы там приводили именно переменные к нужному типу с помощью кастов
В Qt данные преобразуются до кастов, а указывая тип в кастовании просто определяют размер участка памяти к котрому обращаются. Это часто применяется в Qt. Да и кастование в Qt в основном применяется для указателей, а не для результатов вычислений.

Добавлено через 3 минуты
Цитата Сообщение от CEBEP Посмотреть сообщение
проверил, если написать
C
1
s = (size_t)((end - begin) / step) + 1;
то проблема не решается.
Извини забыл округление
C
1
s = (size_t)((end - begin) / step + 0.5) + 1;
Щто там у тебя за компилятор такой?
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
08.07.2013, 20:41  [ТС]
Цитата Сообщение от Avyyakta Посмотреть сообщение
Щто там у тебя за компилятор такой?
MinGW,
Как-раз хотел в начале написать... округление тут не при чем. проблема не связана с округлением. При параметрах min = 0.0, max = 2.0, step = 1.1, last должно быть 1.1, в данной постановке оно получится 2.2
0
 Аватар для Olivеr
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
08.07.2013, 21:03
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
 
int main(void)
{
    double begin = 1.0, end = 3.0, step = 1.0;
    int size = (end - begin) / step + 1.0;
    cout << size;
    return 0;
}
3
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
08.07.2013, 21:04  [ТС]
Цитата Сообщение от Olivеr Посмотреть сообщение
3
ну да, но это просо прецедент. просто в данном случае погрешность положительная и число (end - begin) / step оказалось немного больше двух. При минимуме = 1e-4, максимуме = 1., и шаге = 5.0e-6 результат вычисления неверный
0
 Аватар для Olivеr
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
08.07.2013, 21:10
CEBEP, в смысле? Вы писали
Цитата Сообщение от CEBEP Посмотреть сообщение
в результате мы получим size = 2, хотя в массиве должны быть 1.0, 2.0 и 3.0.
Разве не 1.0, 2.0, 3.0 ?

Добавлено через 5 минут
Цитата Сообщение от CEBEP Посмотреть сообщение
ну да, но это просо прецедент. просто в данном случае погрешность положительная и число (end - begin) / step оказалось немного больше двух. При минимуме = 1e-4, максимуме = 1., и шаге = 5.0e-6 результат вычисления неверный
у вас какой результат получается?
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
08.07.2013, 21:11  [ТС]
Цитата Сообщение от Olivеr Посмотреть сообщение
у вас какой результат получается?
0.999995
0
 Аватар для Olivеr
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
08.07.2013, 21:13
Ищите проблему у себя
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
 
int main(void)
{
    double begin = 1e-4, end = 1.0, step = 5.0e-6;
    int size = (end - begin) / step + 1.0;
    cout << "int size = " << size;
    double x = (1.0-1.0/10000.0) / (5.0 / 1000000.0) + 1.0;
    cout << "\ndoble size = " << x;
    return 0;
}
Миниатюры
Умножение и деление  
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
08.07.2013, 21:22  [ТС]
Цитата Сообщение от Olivеr Посмотреть сообщение
double x = (1.0-1.0/10000.0) / (5.0 / 1000000.0) + 1.0;
действительно у нас различные результаты. Но ведь мы говорим об ошибках, то есть о случайных явлениях. мне удалось подобрать отношение с отрицательной погрешностью на своём компиляторе и своей машине, на вашей скорее всего комбинация другая. результат работы вашего кода у меня:
Code
1
2
int size =  199980 
doble size =  199981
0
 Аватар для Olivеr
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
08.07.2013, 21:30
CEBEP, ну так сделайте
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
 
int main(void)
{
    double begin = 1e-4, end = 1.0, step = 5.0e-6;
    double x = (end - begin) / step + 1.0;
    int size = x;
    cout << "int size = " << size;
    cout << "\ndouble size = " << x;
    return 0;
}
и не заморачивайтесь)

Добавлено через 1 минуту
Максимальная относительная погрешность для double - 2^-52 если что
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
08.07.2013, 21:40  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(void)
{
    int i = 0;
    while (++i != 320)
    {
        double begin = rand() * 1.0 / rand(), end = begin + rand() * 1.0 / rand(), step = (end - begin) / rand();
        double x = (end - begin) / step + 1.0;
        int size = x;
        if (size != x)
        {
            cout << begin << ' ' << end << ' ' << step << ' ' << x << ' ' << size << endl;
        }
    }
}
вот что у меня вывалилось... думаю, у вас тоже не будет пустой списко
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0.250713   1.53092   0.000684968   1870   1869 
0.308038   0.580965   3.97389e-05   6869   6868 
2.38421   2.91368   2.01257e-05   26309   26309 
1.258   3.93092   0.000178851   14946   14946 
0.234934   1.35681   4.6073e-05   24351   24350 
0.333733   1.18437   0.000185082   4597   4597 
0.250319   1.34661   6.15654e-05   17808   17808 
0.169182   0.459236   3.04871e-05   9515   9514 
0.85904   1.1179   9.10424e-06   28434   28434 
1.48292   18.3219   0.000769571   21882   21882 
4.12   4.23951   4.44776e-06   26870   26869 
1.66916   7.456   0.000358562   16140   16139 
0.76313   2.32099   0.00012434   12530   12530 
0.136911   0.610822   1.83515e-05   25825   25825 
4.50838   4.79866   3.80598e-05   7628   7627 
2.17057   126.298   0.00402581   30834   30833
Добавлено через 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
int main(void)
{
    int i = 0;
    int right(0);
    int wrong(0);
    while (++i != 320)
    {
        double begin = rand() * 1.0 / rand(), end = begin + rand() * 1.0 / rand(), step = (end - begin) / rand();
        double x = (end - begin) / step + 1.0;
        int size = x;
        if (size != x)
        {
            cout << begin << ' ' << end << ' ' << step << ' ' << x << ' ' << size;
            ++wrong;
        }
        else
        {
            cout << "all right";
            ++right;
        }
    }
    cout << right << ' ' << wrong << endl;
}
счетчики выпали 247 72
0
 Аватар для Olivеr
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
08.07.2013, 21:43
Поправил
Цитата Сообщение от CEBEP Посмотреть сообщение
if (size != x)
на
C++
1
if (size != static_cast<int>(x) )
и пусто

Добавлено через 57 секунд
all right
all right
all right
all right
all right
319 0
0
108 / 108 / 23
Регистрация: 21.03.2010
Сообщений: 445
08.07.2013, 21:52  [ТС]
всё правильно)) оба ошиблись одинаково. то есть если было 3.9999999999999 он его при инициализации size привёл к 3 и при касте так же привёл к 3

Добавлено через 7 минут
это как-раз доказывает, что static_cast и механизм приведения double к int в данном случае работают идентично
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.07.2013, 21:52
Помогаю со студенческими работами здесь

Умножение и деление комплексных чисел
Неправильно умножаются и делятся комплексные числа Код: Main ComplexNumbers A; A.ReadComplexNumbers(); ComplexNumbers B; ...

Оптимизирует ли компилятор деление/умножение double?
Если я пишу double d = ...; for( ...; ...; d *= 2 ) ... или for( ...; ...; d /= 2 ) ... будет ли компилятор...

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

Сложение и вычитание, умножение и деление, сравнение сумм
Уважаемые форумчане! помогите, пожалуйста, нужно написать программу для работы с устаревшей денежной системой Великобритании. В ней...

Умножение/деление длинных целых чисел из строк
у кого есть код 'умножение и деление целых чисел из строк'? заранее спасибо Добавлено через 32 минуты или библиотека и функции


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
Настройка движения справочника по регистру сведений
Maks 29.03.2026
Решение ниже реализовано на примере нетипового справочника "ТарифыМобильнойСвязи" разработанного в конфигурации КА2, с целью учета корпоративной мобильной связи в коммерческом предприятии. . . .
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru