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

LONG VS DOUBLE / INT VS FLOAT

11.06.2014, 12:31. Показов 2293. Ответов 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
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,028
Записей в блоге: 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
Ответ Создать тему
Новые блоги и статьи
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main(). . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru