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

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

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

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

02.08.2011, 13:40. Просмотров 4661. Ответов 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
castaway
Эксперт С++
4884 / 3019 / 370
Регистрация: 10.11.2010
Сообщений: 11,078
Записей в блоге: 10
Завершенные тесты: 1
03.08.2011, 00:42 #46
Цитата Сообщение от grizlik78 Посмотреть сообщение
Потому, что это верхняя граница абсолютного значения ошибки представления целого числа, которую ещё можно исправить.
Это сверх моего понимания...

Цитата Сообщение от grizlik78 Посмотреть сообщение
И способ её исправления — округление до ближайшего целого.
В какую сторону?

Цитата Сообщение от grizlik78 Посмотреть сообщение
То есть если известно, что число должно быть целым, то если истинная ошибка по модулю меньше 0.5, то достаточно просто округлить к ближайшему целому.
Это опять сверх моего понимания... (ключевые слова выделены)
0
easybudda
03.08.2011, 00:42
  #47

Не по теме:

Цитата Сообщение от grizlik78 Посмотреть сообщение
Если число отрицательное...
Вот об этом я как-то не задумался, спасибо!

0
grizlik78
Эксперт С++
1956 / 1449 / 115
Регистрация: 29.05.2011
Сообщений: 3,007
03.08.2011, 01:00 #48
Цитата Сообщение от lazybiz Посмотреть сообщение
В какую сторону?
Для тех, кто на бронепоезде
До ближайшего целого. Этому в школе учат.
23.71 округляется до 24,
23.1 округляется до 23
23.5 округляется до 24
23.499 округляется до 23
-17.6 округляется до -18
-17.3 округляется до -17
-17.5 округляется до -18
-17.49 округляется до -17
Это называется до ближайшего целого.

Добавлено через 13 минут
Цитата Сообщение от lazybiz Посмотреть сообщение
Это сверх моего понимания...
Согласен, предложение сложное. Так бывает.
Дробные числа хранятся в памяти в усечённом виде, так как нет способа представить абсолютно любую дробь конечным количеством битов. Поэтому после умножения, к примеру, 0.11 на 100 мы получим не точно 11, а число близкое к 11, с некоторой ошибкой. Это не вызывает несогласия?
Ошибка может быть как положительной, так и отрицательной.
Кроме того, поскольку 0.11 получается у нас в результате вычитания (когда целую часть отнимаем), то ошибка эта может быть довольно существенной. В общем случае чем больше по модулю целая часть, тем больше будет модуль возможной ошибки.
В результате вместо 11 у нас может получится, к примеру, 11.07 или может 10.95, или ещё какое. Конечно, для получения настолько большой ошибки разрядности int в 32 бита не хватит, но можно ведь и более вместительный тип взять.
Так вот, пока модуль ошибки меньше чем 0.5, эту ошибку можно полностью устранить. Округлением до ближайшего целого.
0
castaway
Эксперт С++
4884 / 3019 / 370
Регистрация: 10.11.2010
Сообщений: 11,078
Записей в блоге: 10
Завершенные тесты: 1
03.08.2011, 01:16 #49
Так
Цитата Сообщение от lazybiz Посмотреть сообщение
почему именно 0.5
?
Я так и не понял. И думаю не я один...

Цитата Сообщение от grizlik78 Посмотреть сообщение
Потому, что это верхняя граница абсолютного значения ошибки представления целого числа, которую ещё можно исправить.
Давай простыми словами.
0
easybudda
Модератор
Эксперт CЭксперт С++
9663 / 5613 / 952
Регистрация: 25.07.2009
Сообщений: 10,776
03.08.2011, 01:17 #50
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
/* ANSI C 99 */
 
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
 
#define signround(d) ( ( (d) < 0.0 ) ? ceil((d) - 0.5) : floor((d) + 0.5) )
#define PRECISION 3
 
int64_t lost_tail_zeros(int64_t num){
    while ( num && ! ( num % 10ll ) )
        num /= 10ll;
    return num;
}
 
int main(void){
    double val;
    
    while ( printf("> ") && scanf("%lf", &val) == 1 ){
        double tmp = signround(val * pow(10.0, PRECISION));
        int64_t iPart = (int64_t)(tmp / pow(10.0, PRECISION));
        int64_t fPart = lost_tail_zeros((int64_t)tmp % (int64_t)(pow(10.0, PRECISION)));
        printf("Int part: %lld  Fract part: %lld\n", iPart, fPart);
    }
    
    exit(0);
}
0
grizlik78
03.08.2011, 01:18
  #51

Не по теме:

Цитата Сообщение от lazybiz Посмотреть сообщение
Давай простыми словами.
А смысл? Помолчу-ка я дальше.

0
castaway
Эксперт С++
4884 / 3019 / 370
Регистрация: 10.11.2010
Сообщений: 11,078
Записей в блоге: 10
Завершенные тесты: 1
03.08.2011, 01:19 #52
Цитата Сообщение от grizlik78 Посмотреть сообщение
А смысл? Помолчу-ка я дальше.
Это будет правильно с твоей стороны.
0
grizlik78
Эксперт С++
1956 / 1449 / 115
Регистрация: 29.05.2011
Сообщений: 3,007
03.08.2011, 01:20 #53
easybudda, а зачем правые нули удаляешь? Они же значащие при заданной разрядности.
0
easybudda
Модератор
Эксперт CЭксперт С++
9663 / 5613 / 952
Регистрация: 25.07.2009
Сообщений: 10,776
03.08.2011, 01:30 #54
Цитата Сообщение от grizlik78 Посмотреть сообщение
easybudda, а зачем правые нули удаляешь?
Да чёрт его знает. Мне так красивше показалось, когда 3.05 раскладывается на 3 и 5, а не на 3 и 50. Может оно и не правильно...
0
grizlik78
Эксперт С++
1956 / 1449 / 115
Регистрация: 29.05.2011
Сообщений: 3,007
03.08.2011, 01:32 #55
Красивше, да
Но семантика-то у них 3 целых и 50 тысячных. Про то что 50 тысячных стали 5-ю сотыми из вывода уже не понять.
0
-=ЮрА=-
Заблокирован
Автор FAQ
03.08.2011, 09:11 #56
Цитата Сообщение от grizlik78 Посмотреть сообщение
Беда-то в том, что я смогу ответить на вопрос почему именно 0.5, а вот сможешь ли ты убедительно ответить почему именно 10^-5? Почему не 0.001 или 0.000001? Ответ "потому что и так работает" выглядит слабо.
Кстати, pow(0.1,4) это не 10^-5
А теперь внимание сюрприз
C++
1
2
3
fpart = floor(val);
        spart = val - fpart;
        cout<<fpart<<" RU "<<int(100.0*spart + pow(10,-12))<<" KOP\r\n";
Скомпилируй и посмотри что и при pow(10,-12) успешно работает, я же говорил что 2,0 будет представляться как 1,9(9), ну да ладно, я к другому - если ты слышал о погрешности то добавляя 0,5 ты вносишь значительную погрешность, а для числа скажем 0,01 вносишь возмущение 5000% - и заявляешь о точности!

Далее
Цитата Сообщение от easybudda Посмотреть сообщение
int64_t iPart = (int64_t)(tmp / pow(10.0, PRECISION));
int64 9223372036854775807
double 1.79769e+308


Рассмотрим случай - я програмно ввёл целую часть 9223372036854775890 - и что тогда???
А если введу только целую часть 1.79769e+308, к какому тогда типу приводить будешь???Я пытался тебе показать что если есть тип данных с максимальным диапазоном, то не следует его целую часть преобразовывать к типу с меньшей разрядностью.
Дробная часть у меня в алгоритме изначально правильно выводилась, так что не нужно приделывать пару дополнительных колёс к коду - эту запись
C++
1
int(100.0*spart + pow(10,-12))
вводил только для копеек.
0
grizlik78
Эксперт С++
1956 / 1449 / 115
Регистрация: 29.05.2011
Сообщений: 3,007
03.08.2011, 11:23 #57
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Скомпилируй и посмотри что и при pow(10,-12) успешно работает
Да пожалуйста. Первая строчка вывода твоя, вторая моя.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <cmath>
 
int main()
{
    double val = 30000.12;
    int fpart;
    double spart;
 
    fpart = floor(val);
    spart = val - fpart;
    std::cout<<fpart<<" RU "<<int(100.0*spart + pow(10,-12))<<" KOP\r\n";
    std::cout<<fpart<<" RU "<<int(100.0*spart + 0.5)<<" KOP\r\n";
    return 0;
}
Вывод для числа 30000.12:
30000 RU 11 KOP
30000 RU 12 KOP

Вот уж сюрприз сюрпризов, ага.
Так почему 10^-12 или 10^-5 или сколько надо-то?

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
а для числа скажем 0,01 вносишь возмущение 5000% - и заявляешь о точности!
Обидно, я столько написал, а оказывается впустую. Ладно хоть не на бумаге.
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Рассмотрим случай - я програмно ввёл целую часть 9223372036854775890 - и что тогда???
Возможно для тебя и это будет сюрпризом, но double не способен сохранить точно такое целое число. То есть здесь ошибка будет уже не копейками исчисляться, а сотнями рублей.

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
А если введу только целую часть 1.79769e+308, к какому тогда типу приводить будешь???
Ежели очень хочется, то можно длинное целое из MPL взять. Только смысла нет. Здесь ошибка будет такая, сколько денег на земле никогда не было и не будет

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Я пытался тебе показать что если есть тип данных с максимальным диапазоном, то не следует его целую часть преобразовывать к типу с меньшей разрядностью.
И здесь беда, так как для точного представления целых чисел int64_t является более вместительным, чем double.
1
Yurii_74
paladin
279 / 179 / 3
Регистрация: 25.02.2009
Сообщений: 592
03.08.2011, 12:43 #58
Мда... тяжёлый тут случай. Лучше займитесь чем-нибудь более полезным (например, класс напишите для хранения сколь угодно большого целого числа, влезающего в оперативку, затем на его основе класс рациональных чисел можно забабахать).

Если по теме, то погрешность у целых чисел наподобие int абсолютная (+/-0,5), а у вещественных (флоуты, даблы там всякие) - относительная (какие-то части процента). Это на предмете Архитектура ЭВМ должны вдалбливать, но многие интересующиеся/способные узнают эту инфу много раньше.
0
easybudda
Модератор
Эксперт CЭксперт С++
9663 / 5613 / 952
Регистрация: 25.07.2009
Сообщений: 10,776
03.08.2011, 12:51 #59
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Рассмотрим случай - я програмно ввёл целую часть 9223372036854775890 - и что тогда???
Ну до фанатизма-то доходить не нужно. Ещё раз повторяю - цель была представить целыми числами целую и дробную части, а не просто вывести на экран, при чём с сомнительной точностью. Если речь о таких больших числах - длинная арифметика в помощь. Но только здесь явно другое было нужно.

Не по теме:

Цитата Сообщение от grizlik78 Посмотреть сообщение
сколько денег на земле никогда не было и не будет
Если в монгольские тугрики пересчитать, то и long double не хватит...

0
-=ЮрА=-
Заблокирован
Автор FAQ
03.08.2011, 13:14 #60
Цитата Сообщение от grizlik78 Посмотреть сообщение
Вот уж сюрприз сюрпризов, ага.
Вбей вот так и давай забудем эту тему
C++
1
2
3
4
5
6
fpart = floor(val);
        spart = val - fpart;
        cout<<fpart<<" RU "<<100.0*spart<<" KOP\r\n";
 
        cout<<"Celay chast'"<<fpart<<"\r\n";
        cout<<"Drobn chast'"<<spart<<"\r\n";
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.08.2011, 13:14
Привет! Вот еще темы с ответами:

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
60
Yandex
Объявления
03.08.2011, 13:14
Ответ Создать тему
Опции темы

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