0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 5
1

LONG VS DOUBLE / INT VS FLOAT

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

Author24 — интернет-сервис помощи студентам
Всем доброго времени суток!
Объясните пожалуйста почему при следующем коде
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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.06.2014, 12:31
Ответы с готовыми решениями:

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

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

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

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

19
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:01 2
Это особенности поведения даблов. Суть в том, что если 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  [ТС] 3
Я думал об этом. Но если выполнить действия
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 4
Вы не совсем правильно оцениваете точность операций. Дабл хранит, если не ошибаюсь, около 20 знаков после запятой, округляя только последний. При этом, в нескольких последних знаках могут быть ошибки. В частности,
C++
1
2
cout.precision(20);
cout << d << endl;
выводит
15.999999999999996447
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
11.06.2014, 13:20 5
Цитата Сообщение от tehnar5 Посмотреть сообщение
около 20 знаков после запятой
Википедия: Число двойной точности
1
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:21 6
Цитата Сообщение от Croessmah Посмотреть сообщение
Википедия: Число двойной точности
Согласен, был не совсем прав, но суть это не меняет, с округлением надо быть осторожнее.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
11.06.2014, 13:24 7
Цитата Сообщение от tehnar5 Посмотреть сообщение
Приводить к целому типу лучше, прибавляя какое-нибудь небольшое число, например, 0.000000001,
0.5
0
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:29 8
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Сообщение от tehnar5
Приводить к целому типу лучше, прибавляя какое-нибудь небольшое число, например, 0.000000001,
0.5
Нет же, тут цель - обрубить дробную часть, а не округлить число по правилам округления

Добавлено через 53 секунды
Да и Ваш способ и для округления не годится для случая отрицательных чисел
0
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 5
11.06.2014, 13:32  [ТС] 9
ЭТО РАБОТАЕТ
Вместо 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
2782 / 1935 / 570
Регистрация: 05.06.2014
Сообщений: 5,600
11.06.2014, 13:38 10
А более надежные способы есть? Или всегда прибавлять 0.000001 и не задумываться?
floor - округление вниз, ceil - округление вверх, round - к ближайшему целому. Иначе - шаманить с флагами процессора, через ассемблерные вставки.
0
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:42 11
Цитата Сообщение от 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 12
Цитата Сообщение от magicofwater Посмотреть сообщение
Почему 0.5
По правилам округления - все что больше 0.5 округлится вверх, все что меньше вниз.
Если надо строго вверх или вниз - fllor и ceil как уже подсказали.

Цитата Сообщение от tehnar5 Посмотреть сообщение
Да и Ваш способ и для округления не годится для случая отрицательных чисел
округление по модулю пока не отменили.
0
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:49 13
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
округление по модулю пока не отменили.
В смысле? Как ни крути, -0.7 должно округляться до -1, если по правилам, а Вы хотите округлить до нуля, так как int(-0.2) == 0
0
2782 / 1935 / 570
Регистрация: 05.06.2014
Сообщений: 5,600
11.06.2014, 13:52 14
Только он тоже возвращает float/double, не знаю, могут ли быть проблемы или нет, но мало ли...
Проблемы у вас были потому что 196/60.0 дало бесконечную дробь, а число разрядов в double конечно. В принципе можно обойти если использовать числа в формате числитель/знаменатель, но не уверен что они есть в стандартной библиотеке. floor же дает целое число, с ним проблем быть не должно. При условии что оно в int влезает.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
11.06.2014, 13:54 15
Цитата Сообщение от tehnar5 Посмотреть сообщение
В смысле?
-(0.7+0.5)
0
31 / 31 / 19
Регистрация: 03.05.2011
Сообщений: 84
11.06.2014, 13:59 16
Цитата Сообщение от Renji Посмотреть сообщение
floor же дает целое число, с ним проблем быть не должно
Да, соглашусь. Вообще, видимо, единственные безопасные в плане точности операции с double - с целыми числами и целыми числами, поделенными на степень двойки, не очень большую
0
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 5
11.06.2014, 16:16  [ТС] 17
Да, соглашусь. Вообще, видимо, единственные безопасные в плане точности операции с 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 18
Цитата Сообщение от magicofwater Посмотреть сообщение
После мозгового штурма (спасибо всем) я написал так (оставлю здесь для истории)
ну т.е нужно было корректное округление до целого, которое с лохматых годов делается прибавлением 0.5 (с учетом знака, для особо пунктуальных )
0
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 5
11.06.2014, 22:47  [ТС] 19
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
ну т.е нужно было корректное округление до целого, которое с лохматых годов делается прибавлением 0.5 (с учетом знака, для особо пунктуальных )
17 строка
e = d + 0.5
Так?
а если учитывать знак то все равно придется использовать функцию (модуль)? Я правильно понял?
А если придется использовать функцию, то почему бы не использовать округление до ближайшего целого? Или так памяти больше тратится или время работы увеличивается? Глупости не наговорил?
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
12.06.2014, 05:14 20
Цитата Сообщение от magicofwater Посмотреть сообщение
А если придется использовать функцию, то почему бы не использовать округление до ближайшего целого? Или так памяти больше тратится или время работы увеличивается? Глупости не наговорил?
Да нормальны все решения, которые дают правильный результат. Выбор - личное дело разработчика.
0
12.06.2014, 05:14
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.06.2014, 05:14
Помогаю со студенческими работами здесь

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

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

Shot int b long double
есть задание нужно поменять местами значения бит в заданном количестве пар бит. Номера бит в парах...

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

float double int
Доброй ночи, препод совсем запарил, то ему не так, то ему не эдак. // 8.2.cpp: определяет точку...

Как написать такое явное преобразование из double в unsigned long int
как написать такое явное преобразование из double в unsigned long int??? спасибо всем кто...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru