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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.58
CEBEP
106 / 106 / 9
Регистрация: 21.03.2010
Сообщений: 440
#1

Умножение и деление - C++

08.07.2013, 17:36. Просмотров 1567. Ответов 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.07.2013, 17:36
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Умножение и деление (C++):

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

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

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

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

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

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

39
CEBEP
106 / 106 / 9
Регистрация: 21.03.2010
Сообщений: 440
08.07.2013, 21:22  [ТС] #16
Цитата Сообщение от Olivеr Посмотреть сообщение
double x = (1.0-1.0/10000.0) / (5.0 / 1000000.0) + 1.0;
действительно у нас различные результаты. Но ведь мы говорим об ошибках, то есть о случайных явлениях. мне удалось подобрать отношение с отрицательной погрешностью на своём компиляторе и своей машине, на вашей скорее всего комбинация другая. результат работы вашего кода у меня:
Код
int size =  199980 
doble size =  199981
0
Olivеr
412 / 408 / 13
Регистрация: 06.10.2011
Сообщений: 831
08.07.2013, 21:30 #17
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
CEBEP
106 / 106 / 9
Регистрация: 21.03.2010
Сообщений: 440
08.07.2013, 21:40  [ТС] #18
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;
        }
    }
}
вот что у меня вывалилось... думаю, у вас тоже не будет пустой списко
Код
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
412 / 408 / 13
Регистрация: 06.10.2011
Сообщений: 831
08.07.2013, 21:43 #19
Поправил
Цитата Сообщение от 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
CEBEP
106 / 106 / 9
Регистрация: 21.03.2010
Сообщений: 440
08.07.2013, 21:52  [ТС] #20
всё правильно)) оба ошиблись одинаково. то есть если было 3.9999999999999 он его при инициализации size привёл к 3 и при касте так же привёл к 3

Добавлено через 7 минут
это как-раз доказывает, что static_cast и механизм приведения double к int в данном случае работают идентично
0
Olivеr
412 / 408 / 13
Регистрация: 06.10.2011
Сообщений: 831
08.07.2013, 22:08 #21
Цитата Сообщение от CEBEP Посмотреть сообщение
3.9999999999999
а что вы предлагаете записывать в переменную size? 3 или 4?
а если при следующих условиях?
begin = 0.0000000000
end = 1.0000000000
step = 0.7679770188
size = 2.3021222974
2 или 3?

begin = 0.0000000000
end = 1.0000000000
step = 0.6458234048
size = 1.5484109008
1 или 2?
0
CEBEP
106 / 106 / 9
Регистрация: 21.03.2010
Сообщений: 440
08.07.2013, 22:27  [ТС] #22
begin = 0.0000000000
end = 1.0000000000
step = 0.7679770188
size = 2.3021222974
2.

begin = 0.0000000000
end = 1.0000000000
step = 0.6458234048
size = 1.5484109008
1.
0
Olivеr
412 / 408 / 13
Регистрация: 06.10.2011
Сообщений: 831
08.07.2013, 22:28 #23
а при 3.9999999999999 ? 3?
0
CEBEP
106 / 106 / 9
Регистрация: 21.03.2010
Сообщений: 440
09.07.2013, 08:30  [ТС] #24
не, 4
0
Avyyakta
0 / 0 / 0
Регистрация: 08.07.2013
Сообщений: 19
09.07.2013, 19:40 #25
Цитата Сообщение от CEBEP Посмотреть сообщение
MinGW,
Как-раз хотел в начале написать... округление тут не при чем. проблема не связана с округлением. При параметрах min = 0.0, max = 2.0, step = 1.1, last должно быть 1.1, в данной постановке оно получится 2.2
Сначало определись как вычислять каждый элемент. То что привел, ни в какие ворота не лезит, так как begin тогда должен быть -1.1. Проверь....
0
CEBEP
106 / 106 / 9
Регистрация: 21.03.2010
Сообщений: 440
09.07.2013, 20:40  [ТС] #26
h:
C++ (Qt)
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
#ifndef CINTERVAL_H
#define CINTERVAL_H
#include <iostream>
#include <limits>
#include <QTextStream>
#include <QDataStream>
#include <QDebug>
 
class CInterval
{
    size_t s;
    double st;
    double min;
public:
    CInterval();
    CInterval(double begin, double step, double end);
    CInterval(double begin, double step, size_t size);
    CInterval(double begin, double step, int size);
    static CInterval interval(double begin, double end, size_t size);
    inline double first() const { return min; }
    inline double last() const { return min + st * (s - 1); }
    inline double step() const { return st; }
    inline bool isEmpty() const { return static_cast<bool>(s); }
    inline size_t size() const { return s; }
 
    inline double operator[] (int i) const { return min + st * i; }
    inline bool operator !=(const CInterval& v) const { return v.s != s || v.min != min || v.st != st; }
    inline bool operator ==(const CInterval& v) const { return v.s == s && v.min == min && v.st == st; }
 
    friend std::ostream& operator << (std::ostream& out, const CInterval& i);
    friend std::istream& operator >> (std::istream& in, CInterval& i);
    friend QTextStream& operator << (QTextStream& out, const CInterval& i);
    friend QTextStream& operator >> (QTextStream& in, CInterval& i);
    friend QDataStream& operator << (QDataStream& out, const CInterval& i);
    friend QDataStream& operator >> (QDataStream& out, CInterval& i);
    friend QDebug operator << (QDebug out, const CInterval& i);
};
 
#endif // CINTERVAL_H
cpp:
C++ (Qt)
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
#include "cinterval.h"
 
CInterval::CInterval() {}
 
CInterval::CInterval(double begin, double step, double end)
{
    if ((begin > end && step > 0) || (step < 0 && begin < end))
    {
        double c(begin);
        begin = end;
        end = c;
    }
    min = begin;
    st = step;
    qDebug() << QString::number((end - begin) / step, 'g', 200) << static_cast<size_t>((end - begin) / step);
    s = static_cast<size_t>((end - begin) / step) + 1;
}
 
CInterval CInterval::interval(double begin, double end, size_t size)
{
    return CInterval(begin, (end - begin) / size, size + 1);
}
 
CInterval::CInterval(double begin, double step, size_t size)
    : s(size)
    , st(step < 0 ? -step : step)
    , min(begin) { }
CInterval::CInterval(double begin, double step, int size)
    : s(static_cast<size_t>(size))
    , st(step < 0 ? -step : step)
    , min(begin) { }
 
QDataStream& operator << (QDataStream &out, const CInterval &i)
{
    return out << static_cast<quint32>(i.s) << static_cast<qreal>(i.min) << static_cast<qreal>(i.st);
}
std::ostream& operator << (std::ostream& out, const CInterval& i)
{
    return out << i.s << ' ' << i.min << ' ' << i.st;
}
QTextStream& operator << (QTextStream& out, const CInterval& i)
{
    return out << i.s << ' ' << i.min << ' ' << i.st;
}
QDebug operator << (QDebug out, const CInterval& i)
{
    return out << "CInterval(" << i.first() << ':' << i.step() << ':' << i.last() << ')';
}
 
QDataStream& operator >> (QDataStream& in, CInterval& i)
{
    return in >> i.s >> i.min >> i.st;
}
std::istream& operator >> (std::istream& in, CInterval& i)
{
    return in >> i.s >> i.min >> i.st;
}
QTextStream& operator >> (QTextStream& in, CInterval& i)
{
    return in >> i.s >> i.min >> i.st;
}
то что есть на данный момент в исходном виде
0
ValeryS
Модератор
6652 / 5061 / 470
Регистрация: 14.02.2011
Сообщений: 16,923
09.07.2013, 20:49 #27
я не понял о чем спор
об округлении
3.9 должно быть 4?
3.2 3?
вот так
C++
1
2
3
int n;
double b=3.999;
n=b+0.5;
Добавлено через 2 минуты
Цитата Сообщение от CEBEP Посмотреть сообщение
size = static_cast<size_t>((end - begin) / step) + 1;
C++
1
size = (((end - begin) / step) +0.5)+ 1;
0
CEBEP
106 / 106 / 9
Регистрация: 21.03.2010
Сообщений: 440
09.07.2013, 20:53  [ТС] #28
Цитата Сообщение от ValeryS Посмотреть сообщение
об округлении
нет, речь не об округлении... на данный момент проблему можно сформулировать следующим образом:
На компиляторе MinGW выражение
C++ (Qt)
1
(end - begin) / step
при begin = 0.0001 step = 5e-06 и end = 1.0 имеет значение 199979.99999999997089616954326629638671875 и при приведении к целому типу принимает значение 199979, хотя математически результат - целое число 199980
0
ValeryS
Модератор
6652 / 5061 / 470
Регистрация: 14.02.2011
Сообщений: 16,923
09.07.2013, 21:00 #29
Цитата Сообщение от CEBEP Посмотреть сообщение
при begin = 0.0001 step = 5e-06 и end = 1.0 имеет значение 199979.99999999997089616954326629638671875 и при приведении к целому типу принимает значение 199979, хотя математически результат - целое число 199980
еще раз
прибавь 0.5
199979.99999999997089616954326629638671875+0.5=199980.49999999997089616954326629638671875
приведи к целому и получишь 199980
можешь добавить 0.05 или 0.0005
до куда тебе нужно округлить
0
CEBEP
106 / 106 / 9
Регистрация: 21.03.2010
Сообщений: 440
09.07.2013, 21:03  [ТС] #30
Цитата Сообщение от ValeryS Посмотреть сообщение
до куда тебе нужно округлить
мне нельзя округлять. ситуация, когда begin = 0, end = 4e-8, step = 1.001e-8, size должен быть равен 3 а last() возвращать 3.003e-8
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.07.2013, 21:03
Привет! Вот еще темы с ответами:

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

Сделать сложение, вычитание, умножение и деление длинных чисел - C++
В общем, задача такая, что надо сделать сложение, вычитание, умножение и деление длинных чисел. Сумму сделал, с вычитанием какая-то засада....

создать библиотеку из 5 функций: сложение, вычетание, деление, умножение и выделение корня - C++
Нужно срочно сделать курсовую работу, а код написать не могу , как бы ни старался :( задача: создать библиотеку из 5 функций: сложение,...

Написать программу для работы с двоичными числами (сумма, вычитание, умножение и деление) - C++
Доброго времени суток. Задание такое: Разработать программный продукт для осуществления арифметических операций над двоичными числами. При...


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

Или воспользуйтесь поиском по форуму:
30
Yandex
Объявления
09.07.2013, 21:03
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru