Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.59/27: Рейтинг темы: голосов - 27, средняя оценка - 4.59
Noname2512
4 / 4 / 0
Регистрация: 25.06.2010
Сообщений: 106
#1

непонятки

02.08.2011, 13:40. Просмотров 4849. Ответов 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
Ответы с готовыми решениями:

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

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

Непонятки с классами
Народ, уже всё перерыл, впервые с проблемой столкнулся :( Создаю консольное...

непонятки с указателями
Добрый день! изучаем плюсы, наткнулся на одну странную ситуацию, не могу...

Непонятки с итераторами
Здравствуйте, господа программисты. Пытался написать вот эту задачку, но...

81
Jupiter
Каратель
Эксперт С++
6569 / 3990 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
02.08.2011, 13:50 #2
Цитата Сообщение от Noname2512 Посмотреть сообщение
объясните почему без "+0.5" ничего не работает
что значит не работает? приведите пример
0
Noname2512
4 / 4 / 0
Регистрация: 25.06.2010
Сообщений: 106
02.08.2011, 13:54  [ТС] #3
выводит на 1 меньше
пример :
ввожу 3.05
он мне выводит 3 и 4
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,050
02.08.2011, 14:00 #4
Из-за неточного представления не целых чисел. 0.5 для округления результата к ближайшему целому (для отрицательных чисел надо было бы вычитать 0.5)
0
OstapBender
584 / 523 / 75
Регистрация: 22.03.2011
Сообщений: 1,585
02.08.2011, 14:08 #5
используйте функцию modf
0
Noname2512
4 / 4 / 0
Регистрация: 25.06.2010
Сообщений: 106
02.08.2011, 14:23  [ТС] #6
Цитата Сообщение от grizlik78 Посмотреть сообщение
Из-за неточного представления не целых чисел. 0.5 для округления результата к ближайшему целому (для отрицательных чисел надо было бы вычитать 0.5)
Да, но почему для четных все работает хорошо ?
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,050
02.08.2011, 14:26 #7
Цитата Сообщение от Noname2512 Посмотреть сообщение
Да, но почему для четных все работает хорошо ?
Случайность. Ошибка представления числа может быть как в меньшую, так и в большую сторону (ошибка маленькая, вроде +0.001 и -0.001, на деле ещё меньше). При отбрасывании дробной части положительная ошибка просто отбрасывается, а отрицательная приводит к уменьшению результата на 1. Прибавление 0.5 сводит обе ошибки к положительной (+0.501 и +0.499).
1
Kastaneda
Jesus loves me
Эксперт С++
4823 / 2997 / 345
Регистрация: 12.12.2009
Сообщений: 7,559
Записей в блоге: 2
Завершенные тесты: 1
02.08.2011, 14:45 #8
Цитата Сообщение от grizlik78 Посмотреть сообщение
ошибка маленькая, вроде +0.001 и -0.001, на деле ещё меньше
C++
1
std::cout<<std::numeric_limits<double>::epsilon();
У меня это число 2.22045e-016.
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,050
02.08.2011, 15:06 #9
На самом деле ошибка зависит от числа, и в большой степени от целой части исходного числа:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
using namespace std;
 
int main()
{
    double d;
    d = 3.05;
    cout << 5.0 - (( d - int(d) )*100) << endl;
    d = 30.05;
    cout << 5.0 - (( d - int(d) )*100) << endl;
    d = 300.05;
    cout << 5.0 - (( d - int(d) )*100) << endl;
    return 0;
}
Вывод:
1.77636e-14
-7.10543e-14
-1.13687e-12
0
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2011, 16:40 #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
#include <iostream.h>
 
int main()
{
    char ch;
    double val;
 
    double spart;
    int fpart;
    do
    {
        cout<<"Enter double\r\n";
        cin>>val;
 
        fpart = int(val/2)*2;
        spart = val - fpart;
 
        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
Миниатюры
непонятки  
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,050
02.08.2011, 16:44 #11
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Я бы вот так реализовывал разбиение на целую и дробную части
Enter double
11.33
Celay chast'10
Drobn chast'1.33
[Y/N] - Y - Enter new value

Хе-хе. Изобретатель.
0
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2011, 16:54 #12
Цитата Сообщение от grizlik78 Посмотреть сообщение
Хе-хе. Изобретатель.
Спасибо за язву алгоритм как оказалось ещё проще. Как говорится всё гениальное просто...
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
//http://www.cyberforum.ru/cpp-beginners/thread338338.html
#include <iostream.h>
 
int main()
{
    char ch;
    double val;
 
    double spart;
    int fpart;
    do
    {
        cout<<"Enter double\r\n";
        cin>>val;
 
        fpart = int(val);
        spart = val - fpart;
 
        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, 16:55 #13
PS:Всему кому захочеться отпостить что int меньше чем double предлагаю поставить тип fpart ULONG
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,050
02.08.2011, 16:56 #14
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Спасибо за язву
Всегда пожалуйста.

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
алгоритм как оказалось ещё проще
И чем он теперь принципиально отличается от алгоритма в исходном посте? Только тем, что не делается необходимый перевод в целые?
0
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2011, 17:04 #15
Цитата Сообщение от grizlik78 Посмотреть сообщение
Только тем, что не делается необходимый перевод в целые?
Я вообще не пойму почему у ТС не идётт. Алгоритм некоректен только в случае если дабл больше INT_MAX. Вобще можно было бы вот так написать
C++
1
( d - int(d) )*100.0;
Если нужно принципиально по другому без использования функции int то нужно юзать множественное деление на 10, мне код приводить или всё таки додумаешь как это???
0
castaway
Эксперт С++
4929 / 3036 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
02.08.2011, 17:05 #16
Лучший вариант это как сказал OstapBender - modf.
Или такой:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
    double  a = 1.2;
 
    int a_i;
    double  a_f;
 
    a_i = floor( a );
    a_f = a - a_i;
 
    printf( "a = %f\na_i = %d\na_f = %f\n", a, a_i, a_f );
 
    return 0;
}
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,050
02.08.2011, 17:09 #17
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Если нужно принципиально по другому без использования функции int
Дело не в этом. Просто задача состоит в том, чтобы представить дробное число, в котором всего 2 цифры после точки, в виде двух целых: например рубли и копейки. Вот без округления может возникать ошибка в одну копейку.
Правда в финансовых программах, насколько знаю, вообще стараются обходиться без чисел с плавающей точкой.

Добавлено через 41 секунду
Цитата Сообщение от lazybiz Посмотреть сообщение
Лучший вариант это как сказал OstapBender - modf.
Это не избавит от проблемы перевода в целое
0
-=ЮрА=-
Заблокирован
Автор FAQ
02.08.2011, 17:16 #18
А чем код lazybiz плох?
ТС о функциях ceil и floor можно сдесь прочесть
http://www.cplusplus.com/reference/clibrary/cmath/floor/
о modf здесь
http://www.cplusplus.com/reference/clibrary/cmath/modf/
0
castaway
Эксперт С++
4929 / 3036 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
02.08.2011, 17:17 #19
Цитата Сообщение от grizlik78 Посмотреть сообщение
Это не избавит от проблемы перевода в целое
А зачем переводить и какая такая проблема? Нужна целая и дробная части? Пожалуйста!)
Или я суть темы не уловил?...
0
grizlik78
Эксперт С++
1983 / 1476 / 191
Регистрация: 29.05.2011
Сообщений: 3,050
02.08.2011, 17:20 #20
Цитата Сообщение от lazybiz Посмотреть сообщение
А зачем переводить и какая такая проблема? Нужна целая и дробная части? Пожалуйста!)
Или я суть темы не уловил?...
Ещё раз, например нужно из суммы 123.45 выделить рубли и копейки. И то, и другое должно быть целыми числами

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
А чем код lazybiz плох?
А чем код ТС плох? Он вполне себе работает (ну про ограничения разрядности ты и сам говорил)

Добавлено через 43 секунды
Цитата Сообщение от lazybiz Посмотреть сообщение
Или я суть темы не уловил?...
Вопрос был простой: зачем прибавлять 0.5
0
02.08.2011, 17:20
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.08.2011, 17:20

Непонятки со scanf
char str_check; //строка для функции &quot;check&quot;, которая проверяет введенные...

Непонятки с wchar_t
Прошу помощи: что-то не так с wchar_t. Не копирует имена файлов. Содержание...

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


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

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

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