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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 37, средняя оценка - 4.65
Noname2512
4 / 4 / 1
Регистрация: 25.06.2010
Сообщений: 106
#1

непонятки - C++

02.08.2011, 13:40. Просмотров 4762. Ответов 81

у меня есть прога которая берет дабл и разделяет его на две сост. целое и дробное
C++
1
2
this->z = int(d);
this->p = ( d - int(d) )*100+0.5;
объясните почему без "+0.5" ничего не работает для чисел чья дробная часть( нечетная и меньше равна 9 )?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.08.2011, 13:40
Здравствуйте! Я подобрал для вас темы с ответами на вопрос непонятки (C++):

непонятки с for - C++
Издавна мучает вопрос почему некоторые используют в цикле for ( int i = n; i < m ; i++), а другая часть населения for ( int i = n; i < m ;...

Непонятки с bind2nd - C++
Привет. Вот к примеру есть такой код: #include <algorithm> #include <functional> #include <iostream> #include <array> ...

Непонятки с классами - C++
Народ, уже всё перерыл, впервые с проблемой столкнулся :( Создаю консольное приложение: файл class.h #pragma once class Order{ ...

Непонятки с итераторами - C++
Здравствуйте, господа программисты. Пытался написать вот эту задачку, но получается что-то нехорошее. Помогите, пожалуйста! #include...

Непонятки со scanf - C++
char str_check; //строка для функции "check", которая проверяет введенные данные { scanf("%s",&str_check); } выскакивает...

Непонятки с wchar_t - C++
Прошу помощи: что-то не так с wchar_t. Не копирует имена файлов. Содержание program_config.txt config.cfg C:\\Projects\\abx.txt...

81
diagon
Higher
1932 / 1198 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
02.08.2011, 18:00 #31
Цитата Сообщение от lazybiz Посмотреть сообщение
Тут как ни пиши в любом случае в какую-то сторону нужно округлять
Есть decimal в с#, есть длинная арифметика. Обычно их в финансах используют...
0
grizlik78
Эксперт С++
1974 / 1467 / 122
Регистрация: 29.05.2011
Сообщений: 3,034
02.08.2011, 18:13 #32
В C99 есть функция round(), которая делает нужное округление. Но можно её и самостоятельно реализовать, например так:
C
1
2
3
4
5
6
double round(double x)
{
    if (x < 0)
        return ceil(x - 0.5);
    return floor(x + 0.5);
}
Добавлено через 1 минуту
Ну а про то, что в финансах double не используют я уже тоже говорил
0
easybudda
Модератор
Эксперт CЭксперт С++
9722 / 5673 / 972
Регистрация: 25.07.2009
Сообщений: 10,916
02.08.2011, 19:02 #33
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <math.h>
 
#define PRECISION 3 /* digits after point */
 
int main(void){
    double val;
    int fract;
    
    while ( printf("Value: ") && scanf("%lf", &val) == 1 ){
        fract = (int)((val - floor(val)) * pow(10.0, PRECISION) + 0.5);
        while ( fract && ! ( fract % 10 ) )
            fract /= 10;
        printf("Int part: %d Fract part: %d\n", (int)val, fract);
    }
    
    return 0;
}
0
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2011, 22:02 #34
Цитата Сообщение от grizlik78 Посмотреть сообщение
В C99 есть функция round(), которая делает нужное округление. Но можно её и самостоятельно реализовать, например так:
Код C
1
2
3
4
5
6
double round(double x)
{
* * if (x < 0)
* * * * return ceil(x - 0.5);
* * return floor(x + 0.5);
}
Добавлено через 1 минуту
Ну а про то, что в финансах double не используют я уже тоже говорил
Вот тебе код, чтобы ты удовлетворился, всё дело было в точности округления, если округляем до копейки то добавив к дробной части 10^-5 будем иметь погрешность 0,1% что считай ноль
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
#include <iostream.h>
#include <math.h>
 
int main()
{
        char ch;
        double val;
 
        double fpart;
        double spart;
        do
        {
                cout<<"Enter double\r\n";
                cin>>val;
 
                fpart = floor(val);
                spart = (val - fpart);
                cout<<fpart<<" RU "<<int(spart*100 + pow(0.1,4))<<" KOP\r\n";
 
                cout<<"Celay chast'"<<fpart<<"\r\n";
                cout<<"Drobn chast'"<<spart<<"\r\n";
 
                cout<<"[Y/N] - Y - Enter new value\r\n";
                cin>>ch;
        }
        while(ch == 'Y' || ch == 'y');
        return 0;
}
0
Изображения
 
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2011, 22:05 #35
Цитата Сообщение от easybudda Посмотреть сообщение
fract = (int)((val - floor(val)) * pow(10.0, PRECISION) + 0.5);
опять это зловещее 0,5О_о,ребят ну без него же ведь работает

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
int(spart*100 + pow(0.1,4))
0
easybudda
Модератор
Эксперт CЭксперт С++
9722 / 5673 / 972
Регистрация: 25.07.2009
Сообщений: 10,916
02.08.2011, 22:10 #36
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
опять это зловещее 0,5,ребят ну без него же ведь работает
А что в нём зловещего?

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
int(spart*100 + pow(0.1,4))
Это что?
0
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2011, 22:14 #37
Ну просто зачем ещё 0,5 добавлять, почти во всех постах оно сквозит, достаточно добавить 10^-5 чтобы преобразование int() было корректным



Цитата Сообщение от easybudda Посмотреть сообщение
int(spart*100 + pow(0.1,4))
Это что?
ответ в коде в моём посте выше
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
double fpart;
        double spart;
        do
        {
                cout<<"Enter double\r\n";
                cin>>val;
 
                fpart = floor(val);
                spart = (val - fpart);
                cout<<fpart<<" RU "<<int(spart*100 + pow(0.1,4))<<" KOP\r\n";
 
                cout<<"Celay chast'"<<fpart<<"\r\n";
                cout<<"Drobn chast'"<<spart<<"\r\n";
вобщем pow(0.1,4) - думаю можно сказать что это погрешность округления, вобще изначально мне не понятно почему int(spart*100) не давало желаемого результата, возможно дабл для системы представлябтся как 2.0 = 1,9(9) ???
0
easybudda
Модератор
Эксперт CЭксперт С++
9722 / 5673 / 972
Регистрация: 25.07.2009
Сообщений: 10,916
02.08.2011, 22:23 #38
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
вобщем pow(0.1,4) - думаю можно сказать что это погрешность округления, вобще изначально мне не понятно почему int(spart*100) не давало желаемого результата, возможно дабл для системы представлябтся как 2.0 = 1,9(9) ???
Вот и за чем это нужно, если прибавление 0.5 к округляемой величине даёт понятный и предсказуемый результат?
0
castaway
Эксперт С++
4919 / 3027 / 372
Регистрация: 10.11.2010
Сообщений: 11,085
Записей в блоге: 10
Завершенные тесты: 1
02.08.2011, 22:25 #39
Цитата Сообщение от diagon Посмотреть сообщение
Есть decimal в с#, есть длинная арифметика. Обычно их в финансах используют...
Отлично. Я очень рад за C#.

Цитата Сообщение от grizlik78 Посмотреть сообщение
Но повторю ещё раз. Код в исходном посте вполне рабочий и решает поставленную задачу. Вопрос был только в том, почему он такой.
Цитата Сообщение от grizlik78 Посмотреть сообщение
Ну а про то, что в финансах double не используют я уже тоже говорил
Вот именно. Почему он такой? И при чем тут финансы-хринансы я вообще не пойму. Автор поста про финансы ни слова не сказал.
0
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2011, 22:31 #40
Цитата Сообщение от easybudda Посмотреть сообщение
от и за чем это нужно, если прибавление 0.5 к округляемой величине даёт понятный и предсказуемый результат?
pow(0.1,4) - даёт тоже, ну и как мне кажется алгоритм внешне выглядит проще
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
fpart = floor(val);
* * * * * * * * spart = (val - fpart);
* * * * * * * * cout<<fpart<<" RU "<<int(spart*100 + pow(0.1,4))<<" KOP\r\n";
Чем разбирать дробную часть на цифры

Цитата Сообщение от easybudda Посмотреть сообщение
fract = (int)((val - floor(val)) * pow(10.0, PRECISION) + 0.5);
* * * * * * * * while ( fract && ! ( fract % 10 ) )
* * * * * * * * * * * * fract /= 10;
Цитата Сообщение от easybudda Посмотреть сообщение
(int)val
- если модуль val будет превосходить INT_MAX не будет потери точности вычислений???
0
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2011, 22:36 #41
Просто констатация фактов
0
Миниатюры
непонятки  
easybudda
Модератор
Эксперт CЭксперт С++
9722 / 5673 / 972
Регистрация: 25.07.2009
Сообщений: 10,916
02.08.2011, 23:23 #42
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
- если модуль val будет превосходить INT_MAX не будет потери точности вычислений?
Конечно будет. Замените int на int64_t, чтобы ни о чём плохом не думать... Задача-то, на сколько я понял, выдать по отдельности целыми числами целую и дробную части. У меня как-раз это и происходит (при учёте, что и та и другая помещаются в INT_MAX (INT_MIN)), а у Вас?
0
grizlik78
Эксперт С++
1974 / 1467 / 122
Регистрация: 29.05.2011
Сообщений: 3,034
02.08.2011, 23:51 #43
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Ну просто зачем ещё 0,5 добавлять, почти во всех постах оно сквозит, достаточно добавить 10^-5 чтобы преобразование int() было корректным
Беда-то в том, что я смогу ответить на вопрос почему именно 0.5, а вот сможешь ли ты убедительно ответить почему именно 10^-5? Почему не 0.001 или 0.000001? Ответ "потому что и так работает" выглядит слабо.
Кстати, pow(0.1,4) это не 10^-5
0
castaway
Эксперт С++
4919 / 3027 / 372
Регистрация: 10.11.2010
Сообщений: 11,085
Записей в блоге: 10
Завершенные тесты: 1
03.08.2011, 00:18 #44
grizlik78,
Цитата Сообщение от grizlik78 Посмотреть сообщение
почему именно 0.5
?
0
grizlik78
Эксперт С++
1974 / 1467 / 122
Регистрация: 29.05.2011
Сообщений: 3,034
03.08.2011, 00:36 #45
Потому, что это верхняя граница абсолютного значения ошибки представления целого числа, которую ещё можно исправить. И способ её исправления — округление до ближайшего целого.
То есть если известно, что число должно быть целым, то если истинная ошибка по модулю меньше 0.5, то достаточно просто округлить к ближайшему целому. Если ошибка больше, то её не исправить.
Алгоритм округления я показывал в функции:
Если число положительное, то надо добавить 0.5 и округлить к минус бесконечности (floor).
Если число отрицательное, то надо вычесть 0.5 и округлить к плюс бесконечности (ceil).
1
03.08.2011, 00:36
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.08.2011, 00:36
Привет! Вот еще темы с ответами:

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

Непонятки с синтаксисом - C++
В заголовочном файле мне встретилось такое описание класса: class source_mcast_reciever { uint16_t m_port; ...

Непонятки со списком - C++
Нашёл код в интернете и немного не понимаю его в некоторых местах. Объясните мне пожалуйста, зачем в коде вот тут: ...

непонятки с указателями - C++
Добрый день! изучаем плюсы, наткнулся на одну странную ситуацию, не могу сообразить, в чём дело... :( Есть структура - Point...


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

Или воспользуйтесь поиском по форуму:
45
Ответ Создать тему
Опции темы

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