![]() |
Модераторы: bsa |
![]() ![]() ![]() |
|
den140387 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 9 Регистрация: 21.12.2011 Репутация: нет Всего: нет |
Добрый День!
Прошу помочь в написании кода преобразовании вещественной части long double в целочисленное значение. То есть должно быть что-то типа: long double ld = 123.456; int c = func( ld); // c = 456 Проблема в том, чтобы написать эту процедуру func. Число типа long double пользователь должен ввести с клавиатуры. Точность заранее неизвестна. Пробывал написать след. образом:
Задумка моя в том, чтобы каждый раз умножать на 10 до тех пор, пока плавающая часть не станет равной 0. То есть, если пользователь ввел: ld = 12.34, то ldval = 0.34 Далее в цикле ldval = 0.34, 3.4, 34.00 Но проблема в том, что 34.00 и 34 - это не два одинаковых числа, то есть разница между ними не равна 0. Я прочитал про вещественные и целочисленные типы, понимаю, почему они не равны, но не представляю, как решить данную задачу. Просьба помочь в решении данной задачи. Может быть есть какая-то константа, позволяющая сравнивать на равенство целочисленные и вещественные типы? Прежде чем задать вопрос я погуглить, но ничего полезного не нашел.. |
|||
|
||||
SenkraD |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 3.2.2006 Где: Украина::Киев Репутация: нет Всего: 23 |
Ну вы же читали про вещественные типы
![]()
|
|||
|
||||
den140387 |
|
||||
Новичок Профиль Группа: Участник Сообщений: 9 Регистрация: 21.12.2011 Репутация: нет Всего: нет |
Спасибо! ![]() Я читал про них в Лафоре и Липпмане. Там говорится только то, что long double имеет точность в 19 цифр, если я правильно помню. В связи с этим вопрос: почему вы выбрали именно "0.001", а не "0.01" или же "0.00001"? Раз точность 19 цифр, то по идее 18-ть нулей должно быть, если я ничего не путаю.. |
||||
|
|||||
feodorv |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Так, для понимания Вашего понимания, почему? А что такое "вещественная часть long double"? Дробная часть? Тогда в общем случае задача не имеет (правильного) решения.
Ну, код, который Вы привели, несколько отличается от этого:
Отличие именно в том, что значение для long double не задано, а вводится с клавиатуры. Тогда задача имеет решение, ибо можно вводить его не сразу в long double, а в строку. Затем эту строку можно проанализировать на тему, что это действительно строковое представление вещественного числа. А уже потом найти точку и вычислить искомое (с проверкой на переполнение). -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||
|
|||||||
den140387 |
|
||||||
Новичок Профиль Группа: Участник Сообщений: 9 Регистрация: 21.12.2011 Репутация: нет Всего: нет |
Как я понимаю, они просто по-другому в памяти машины представляются. Для плавающих есть мантисса и экспонента, а для целочисленных - нет
Ну как я понимаю, дробная часть с точностью до 19ти цифр. А почему не имеет решения? Мне же известна максимальная точность long double: 19 цифр после запятой.
По поводу строки я уже сделал. Было две задачи: 1) Пользователь вводит строку. Необходимо вывести это же значение в формате long double Это я сделал. 2) Пользователь вводит число типа long double. Оно должно быть прочитано как long double. Необходимо вывести его в виде строки. Целую часть в строку я преобразовал. А вот с дробной возникла проблема. |
||||||
|
|||||||
SenkraD |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 3.2.2006 Где: Украина::Киев Репутация: нет Всего: 23 |
|
||||||
|
|||||||
feodorv |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Простите, но это совсем другая задача. Не нужно её сводить к нахождению дробной части в виде беззнакового целого. Да и целая часть long double не обязана умещаться в int или long long. Что Вы будете делать с числом 10^100? Задача (адекватного!) вывода значения double или long double не так проста. Но если требуется простое решение, то, действительно, можно ограничиться определённым количеством знаков (после запятой). Но при этом совсем не нужно представлять целую и дробную части в виде int. Как бы Вы решили задачу строкового представления int? Вот аналогично решается и задача, стоящая перед Вами. Добавлено через 9 минут и 13 секунд
В какую целочисленную переменную типа int Вы собрались запихивать 19 знаков?
Проблема не в этом, а в том, что числа с плавающей точкой имеют двоичное машинное представление. То есть деление на два не разрушает мантиссу, а вот деление на 10 уже даёт приблизительный результат (то есть x / 10 * 10 может уже не равняться x). А мы хотим иметь именно 10тичное строковое представление, которое, увы, не обязано совпадать с нашими ожиданиями (вместо .34 может получиться .33999989889...) -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||
|
|||||
akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Первоначально у нас вводится строковый тип. Так и работайте с ним. Предположим, что точка в вашей текущей локали разделитель целой и дробной части
Это в предположении, что ввод в десятичной системе, но без "E-2", например. Это сообщение отредактировал(а) akizelokro - 20.8.2013, 14:16 -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Вообще-то, он в любом случае вводит строку, если считать для упрощения. Есть в стандарте функции to_tstring (на самом деле to_string и to_wstring, но мне сподручней писать сразу to_tstring) И разные функции обратного преобразования из строки в числовые значения stol, stoi, stod .. Кажисть, правда в С++11 стандарте. но эти функции уже и студия даже поддерживает Это сообщение отредактировал(а) akizelokro - 20.8.2013, 14:26 -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
а если проблема с преобразованием вещественной части и нельзя прибегать к стандартным этим функция преобразования, то берёте вещественную часть и по циклу умножаете каждый раз на 10, новая целая часть даёт очередную цифру вещественной части. Её пишете и целую часть отбрасываете, и снова повтор умножения на 10. И там до тех пор пока результат не станет равен нулю.
-------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Всё так. Но: Результат может никогда не стать равным нулю... -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
den140387 |
|
||||||||||||
Новичок Профиль Группа: Участник Сообщений: 9 Регистрация: 21.12.2011 Репутация: нет Всего: нет |
Спасибо! ![]() Добавлено через 5 минут и 5 секунд
c int - все просто. Я могу легко пройтись по всему целому числу и каждую цифру преобразовать в символ, путем сложения с '0'. В случае обхода целочисленного значения, я могу легко получить условие того, что обработал все цифры этого значения. А вот с вещественными типами проблема из-за того, что я не знаю, когда заканчивается это число. Добавлено через 7 минут и 26 секунд
+1. В способе, который я привел в самом начале, происходило зацикливание. |
||||||||||||
|
|||||||||||||
akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Неочевидно. Десять в минус какой степени там предел? tstring схавает. А если уж кому-то интересно, то можно break на пятитысячной итерации поставить. -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
den140387 |
|
|||
Новичок Профиль Группа: Участник Сообщений: 9 Регистрация: 21.12.2011 Репутация: нет Всего: нет |
Спасибо! ![]() Вы гораздо более понятно объяснили, чем в книжке. |
|||
|
||||
akizelokro |
|
||||||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Это где вы делали сравнение double с интом? Ну-ну! Там вообще с вашим умножением на 10 в цикле может быть неизвестно что. Об этом вам писали уже. Вам надо было сравнивать именно с нулём (значение double), постоянно отсекая целую часть (появившуюся цифру), перенося её в строку. и там уже не нужны никакие ограничения на размер инта. Работа ведётся только с double и string. А привлекать ещё дополнительный тип, когда можно обойтись и без него, нерационально. Единственное, что его можно использовать для того, чтобы цифру, появлюящуюся после умножения на 10 вещественной части преобразовывать в литерал (строку). Есть разница между
и
А вот это именно и есть разница в подходах. Бритва Оккама. О чем и был мой первый пример кода. string может захавать сколько угодно цифр после запятой. А проверку на NaN'ы и прочие эники-беники тоже реализуете Добавлено через 29 секунд И не надо ничего делить на десять. Добавлено через 9 минут и 39 секунд Просто double c int сравнивать никогда не надо. Так, совет на будущее. Потому что результат вообще неочевиден -------------------- a = a + b; b = a - b; a = a - b; |
||||||
|
|||||||
![]() ![]() ![]() |
Правила форума "C/C++: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |