Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/11: Рейтинг темы: голосов - 11, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 5

LONG VS DOUBLE / INT VS FLOAT

11.06.2014, 12:31. Показов 2342. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток!
Объясните пожалуйста почему при следующем коде
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
int main()
{
            long e;
            long a = 196;
            double b = a/60.0;
            cout << "a = " << a << endl;
            cout << "b = " << b << endl;
            long c = static_cast<int>(b); // отбрасывание дробной части
            cout << "c = " << c << endl;
            double d = (b - c) * 60;
            cout << d << endl;
            e = d;
            cout << e << endl;
        return 0;
}
Результат d = 16 (так правильно), а результат e = 15???
Спасибо!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.06.2014, 12:31
Ответы с готовыми решениями:

Размер для данных (int, char, long, double, short, unsigned, float)
Напишите программу, которая будет определять размер для данных (int, char, long, double, short, unsigned, float) и выводить информацию (о...

Создать динамический массив, любого простого типа (например: int, long, float, double)
1. Создать проект, который содержит консольную программу Win32. 2. Создать динамический массив, любого простого типа (например: int,...

Напишите программу, которая будет определять размер для данных (int, char, long, double, short, unsigned, float) и выводить информацию
1. Какие типы данных лучше всего использовать для хранения следующих значений: а) возраст человека в текущем году; б) вес человека в...

19
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:01
Это особенности поведения даблов. Суть в том, что если d = 15.99999999999 вследствие потери точности, то при выведении его как дабла, он округлится нормально, а при выведении как инта целая часть отбросится и будет 15. Приводить к целому типу лучше, прибавляя какое-нибудь небольшое число, например, 0.000000001, чтобы избежать таких потерь в точности

Добавлено через 2 минуты
Вместо e = d надо сделать e = d + 0.000001. Да и
static_cast<int>(b) лучше заменить на static_cast<int>(b + 0.0000001)
0
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 5
11.06.2014, 13:04  [ТС]
Я думал об этом. Но если выполнить действия
a = 196
b = 196/60=3,266667
c = 3
d = (3,266667 - 3) * 60 = 16.00002
Что больше 16. Соответсвенно, если следовать Вашей версии, то ответ должен быть 16.
0
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:17
Вы не совсем правильно оцениваете точность операций. Дабл хранит, если не ошибаюсь, около 20 знаков после запятой, округляя только последний. При этом, в нескольких последних знаках могут быть ошибки. В частности,
C++
1
2
cout.precision(20);
cout << d << endl;
выводит
15.999999999999996447
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
11.06.2014, 13:20
Цитата Сообщение от tehnar5 Посмотреть сообщение
около 20 знаков после запятой
Википедия: Число двойной точности
1
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:21
Цитата Сообщение от Croessmah Посмотреть сообщение
Википедия: Число двойной точности
Согласен, был не совсем прав, но суть это не меняет, с округлением надо быть осторожнее.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
11.06.2014, 13:24
Цитата Сообщение от tehnar5 Посмотреть сообщение
Приводить к целому типу лучше, прибавляя какое-нибудь небольшое число, например, 0.000000001,
0.5
0
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:29
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Сообщение от tehnar5
Приводить к целому типу лучше, прибавляя какое-нибудь небольшое число, например, 0.000000001,
0.5
Нет же, тут цель - обрубить дробную часть, а не округлить число по правилам округления

Добавлено через 53 секунды
Да и Ваш способ и для округления не годится для случая отрицательных чисел
0
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 5
11.06.2014, 13:32  [ТС]
ЭТО РАБОТАЕТ
Вместо e = d надо сделать e = d + 0.000001.
ЭТО НЕ РАБОТАЕТ
Да и static_cast<int>(b) лучше заменить на static_cast<int>(b + 0.0000001)
Почему 0.5, а не 0.6, 0.00001, 0.3?
А более надежные способы есть? Или всегда прибавлять 0.000001 и не задумываться?
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
11.06.2014, 13:38
А более надежные способы есть? Или всегда прибавлять 0.000001 и не задумываться?
floor - округление вниз, ceil - округление вверх, round - к ближайшему целому. Иначе - шаманить с флагами процессора, через ассемблерные вставки.
0
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:42
Цитата Сообщение от magicofwater Посмотреть сообщение
ЭТО НЕ РАБОТАЕТ
Да и static_cast<int>(b) лучше заменить на static_cast<int>(b + 0.0000001)
В данном конкретном случае не работает, так как проблема была только с переменной d. Никаких более надежных способов я не знаю, кроме способа создать свою собственную функцию
C++
1
2
3
4
5
int toInt(double a)
{
    return int(a + 0.0000001);
    return static_cast<int>(a + 0.0000001);
}
Выбирайте любой из двух return-ов, они оба делают, по сути, одно и то же

Добавлено через 2 минуты
Цитата Сообщение от Renji Посмотреть сообщение
floor - округление вниз
Только он тоже возвращает float/double, не знаю, могут ли быть проблемы или нет, но мало ли...
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
11.06.2014, 13:45
Цитата Сообщение от magicofwater Посмотреть сообщение
Почему 0.5
По правилам округления - все что больше 0.5 округлится вверх, все что меньше вниз.
Если надо строго вверх или вниз - fllor и ceil как уже подсказали.

Цитата Сообщение от tehnar5 Посмотреть сообщение
Да и Ваш способ и для округления не годится для случая отрицательных чисел
округление по модулю пока не отменили.
0
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:49
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
округление по модулю пока не отменили.
В смысле? Как ни крути, -0.7 должно округляться до -1, если по правилам, а Вы хотите округлить до нуля, так как int(-0.2) == 0
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
11.06.2014, 13:52
Только он тоже возвращает float/double, не знаю, могут ли быть проблемы или нет, но мало ли...
Проблемы у вас были потому что 196/60.0 дало бесконечную дробь, а число разрядов в double конечно. В принципе можно обойти если использовать числа в формате числитель/знаменатель, но не уверен что они есть в стандартной библиотеке. floor же дает целое число, с ним проблем быть не должно. При условии что оно в int влезает.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
11.06.2014, 13:54
Цитата Сообщение от tehnar5 Посмотреть сообщение
В смысле?
-(0.7+0.5)
0
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:59
Цитата Сообщение от Renji Посмотреть сообщение
floor же дает целое число, с ним проблем быть не должно
Да, соглашусь. Вообще, видимо, единственные безопасные в плане точности операции с double - с целыми числами и целыми числами, поделенными на степень двойки, не очень большую
0
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 5
11.06.2014, 16:16  [ТС]
Да, соглашусь. Вообще, видимо, единственные безопасные в плане точности операции с double - с целыми числами и целыми числами, поделенными на степень двойки, не очень большую
Ваше высказывание вообще не понял

Добавлено через 24 минуты
После мозгового штурма (спасибо всем) я написал так (оставлю здесь для истории)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <math.h>       /* floor, ceil, round (C99 и выше)*/
 
using namespace std;
int main()
{
            long e;
            long a = 196;
            double b = a/60.0;
            cout << "a = " << a << endl;
            cout << "b = " << b << endl;
            long c = static_cast<int>(b); // отбрасывание дробной части
            cout << "c = " << c << endl;
            double d = (b - c) * 60;
            cout << d << endl;
            //e = d+0.0000000001;
            e = roundl (d);
            cout << e << endl;
        return 0;
}
roundl
long double roundl (long double x);
описана тут
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
11.06.2014, 17:17
Цитата Сообщение от magicofwater Посмотреть сообщение
После мозгового штурма (спасибо всем) я написал так (оставлю здесь для истории)
ну т.е нужно было корректное округление до целого, которое с лохматых годов делается прибавлением 0.5 (с учетом знака, для особо пунктуальных )
0
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 5
11.06.2014, 22:47  [ТС]
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
ну т.е нужно было корректное округление до целого, которое с лохматых годов делается прибавлением 0.5 (с учетом знака, для особо пунктуальных )
17 строка
e = d + 0.5
Так?
а если учитывать знак то все равно придется использовать функцию (модуль)? Я правильно понял?
А если придется использовать функцию, то почему бы не использовать округление до ближайшего целого? Или так памяти больше тратится или время работы увеличивается? Глупости не наговорил?
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
12.06.2014, 05:14
Цитата Сообщение от magicofwater Посмотреть сообщение
А если придется использовать функцию, то почему бы не использовать округление до ближайшего целого? Или так памяти больше тратится или время работы увеличивается? Глупости не наговорил?
Да нормальны все решения, которые дают правильный результат. Выбор - личное дело разработчика.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.06.2014, 05:14
Помогаю со студенческими работами здесь

Long float и double
В чем отличие long float от double?

Преобразовать 2 числа int в 1 число float(double) | double int1.int2
Всем привет. Изучая азы C++, столкнулся с такой проблемой. Есть два значения типа int, их необходимо преобразовать в одно значение типа...

Double, int , long double
Как вычислить диапазоны типов вручную указанных в название темы?

Поменять местами значения бит в заданном количестве пар бит
есть задание нужно поменять местами значения бит в заданном количестве пар бит. Номера бит в парах задаются с клавиатуры. используя shot...

Требуется написать функцию long long pow(long long a, unsigned int p), которая возводит число a в степень p
Требуется написать функцию long long pow(long long a, unsigned int p), которая возводит число a в степень p и возвращает ap. Помогите...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита табличной части. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Функция заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru