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

Ошибка при изменении типа данных

24.04.2013, 16:06. Показов 720. Ответов 8
Метки нет (Все метки)

Добрый день.

Возникла следующая задача. Я бы даже сказал загадка.
В программе использовал (int) - операцию перевода числа из типа с плавающей точкой в тип целого числа.

В ходе тестирования оказалось, что выражение:

(int)(2.3 * 100) дает ответ 229, а не 230 как по моему мнению должно было бы быть.

При этом так же не правильные ответы дают выражения с константами (2.32, 2.28, 2.26).

Во всех остальных случаях (из тех которые я тестировал) ответы были правильные, то есть соответствовали моему представлению.

(int)(2.2 * 100) == 220
(int)(2.4 * 100) == 240
(int)(20.3 * 100) == 2030 и т.д.

Если у кого нибудь есть этому объяснение буду признателен.
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.04.2013, 16:06
Ответы с готовыми решениями:

При изменении типа данных ошибка
Доброго времени суток, дорогие форумчане. Делал программу на C# + Access база. При замене в базе...

Ошибка 1004 записи формулы при изменении типа переменной
Dim sb As Currency ' НАКОПЛЕННАЯ СУММА БЕЛКОВ одного приема В ГРАММАХ sb = 6.9 ...

Ошибка при изменении данных
Есть база данных, которая привязана к проекту через Binding Source. Вывожу данные таблицы в...

Ошибка при изменении источника данных
Здравствуйте форумчане. Есть 2 формы, договоры и Find, таблица договоры. Если создать...

8
115 / 115 / 8
Регистрация: 12.04.2013
Сообщений: 379
24.04.2013, 16:43 2
Это связано с представлением числа с плавающей запятой в памяти компьютера - оно далеко не точное.
по этой же причие следующая конструкция приведед к зацикливанию
Код
double t = 10;
while (t != 0) t = t - 0.1;
1
0 / 0 / 1
Регистрация: 24.04.2013
Сообщений: 8
24.04.2013, 17:17  [ТС] 3
Получается что вычислениям значений с плавающей точкой вообще нельзя доверять?

C
1
2
3
4
5
6
int main()
{
    printf ("%lf\n", 2.3 * 100); // дает резульат 230.000000
    printf ("%d\n", (int)230.0000000); // дает результат 230
    printf ("%d\n", (int)(2.3 * 100)); // дает результат 229
}
Одно и тоже выражение в разных ситуациях высчитывается по разному.
Не радует такое положение вещей.
И все же, вспоминая теорию: у всех типов чисел с плавающей точкой есть так называемая разрядность.

float 7-8
double 15-16
long double 19-20

И насколько я знаю под разрядностью как раз понимают то количество знаков в числе с плавающей точкой которым можно доверять.

Реальность же это опровергает.

И какой из этого выход? Я имею ввиду что существую задачи, например математические, когда точность решения критична.
0
115 / 115 / 8
Регистрация: 12.04.2013
Сообщений: 379
24.04.2013, 17:21 4
И какой из этого выход? Я имею ввиду что существую задачи, например математические, когда точность решения критична.
Цитата Сообщение от bur@kov Посмотреть сообщение
printf ("%lf\n", 2.3 * 100); // дает резульат 230.000000
считает же
0
0 / 0 / 1
Регистрация: 24.04.2013
Сообщений: 8
24.04.2013, 21:45  [ТС] 5
считает же
Считает правильно.
Ошибка получается при попытке перевести из одного типа данных в другой.
При чем с помощью специально предназначенной для этого операции.
0
115 / 115 / 8
Регистрация: 12.04.2013
Сообщений: 379
24.04.2013, 21:53 6
Цитата Сообщение от bur@kov Посмотреть сообщение
Считает правильно.
Ошибка получается при попытке перевести из одного типа данных в другой.
При чем с помощью специально предназначенной для этого операции.
ну так вы результат тогда преобразовывайте, то есть сначала в переменную посчитайте, а потом преобразуйте.
0
0 / 0 / 1
Регистрация: 24.04.2013
Сообщений: 8
24.04.2013, 22:24  [ТС] 7
Цитата Сообщение от ChihPih Посмотреть сообщение
ну так вы результат тогда преобразовывайте, то есть сначала в переменную посчитайте, а потом преобразуйте.
Вот в этом то вся и загвоздка.

Переменная которая получает свое значение вводом с клавиатуры или присваиванием конкретного числа в ходе программы, преобразуется без ошибок.

C
1
2
3
double t;
scanf ("%lf", &t);
printf ("%d\n", (int)t);
C
1
2
3
double t;
t = 230.000000;
printf ("%d\n", (int)t);
В обоих случаях ответ будет 230. То есть когда значение переменной определенно пользователем, преобразование происходит правильно. Но как только мы начинаем производить какие либо вычисления ответ становиться непредсказуемым.

C
1
printf ("%d\n", (int)(2.3 * 100));
C
1
2
3
double t;
t = 2.3 * 100;
printf ("%d\n", (int)t);
То есть при попытке перевести переменную типа с плавающей точкой, которая получила свое значение в ходе вычисления, в переменную целого типа результат может быть не правильным.

Добавлено через 12 минут
Я объясню для чего у меня возникла такая необходимость.
Цель число с плавающей точкой (с двумя знаками после точки) разделить на два числа: на то что до точки и на то что после. И присвоить их переменным целого типа.

То есть если переменная double x == 2.35, то должно получить две переменные int y == 2, z == 35.

Для того чтобы выделить дробную чать я сначала x * 100 - то есть смещал запятую на две цифры вправо.
Потом переводил в int - тоесть оставлял только целую часть. И в конец получал остаток от деления на 100 - то есть снова отделял эти две цифры.

C
1
(int)(x * 100) % 100
0
115 / 115 / 8
Регистрация: 12.04.2013
Сообщений: 379
24.04.2013, 22:33 8
Код
double t;
t = 2.3 * 100;
t = rint(t);
printf ("%d\n", (int)t)
1
0 / 0 / 1
Регистрация: 24.04.2013
Сообщений: 8
25.04.2013, 12:48  [ТС] 9
Цитата Сообщение от ChihPih Посмотреть сообщение
Код
double t;
t = 2.3 * 100;
t = rint(t);
printf ("%d\n", (int)t)
Идея понятна. Спасибо.
Единственный момент что функция rint поддерживается стандартом C99. Я компилирую в Microsoft Visual C++ 2010 Express. Он ее не понимает. Поэтому для стандарта 89 г. такое решения не подойдет.

Вообще самый оптимальный вариант это организовать ввод как два целых числа разделенных точкой.

C
1
scanf ("%d.%d", &a, &b);
Если же все таки стоит задача преобразовать число с плавающей точкой, то среди функций стандарта 89 г. нашел:
double ceil (double x); -наименьшее приведенное к double целое >=x;
double floor (double x); -наибольшее приведенное к double целое <=x.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.04.2013, 12:48
Помогаю со студенческими работами здесь

Ошибка при изменении и удалении данных
При удалении выходит &quot;Произошла ошибка: You have an error in your SQL syntax; check the manual that...

Ошибка при изменении данных и попытке сохранения в программе
В общем столкнулся с такой проблемой. Есть вычисляемый столбец &quot;Стаж&quot;. При изменении данных и...

Ошибка при изменении данных через Entity Framework
Столкнулся с проблемой обновления данных, сам еще новичок в Entity. Добавляет в таблицу все ок, но...

Ошибка при выборе типа данных
Всем доброго времени суток, начал самостоятельно изучать плюсы и делать лабы из учебника Павловской...


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

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

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