Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Как получить дробную часть числа ?

1.9K
27 апреля 2006 года
Nigger
71 / / 09.04.2005
Есть ли в BC++ функция для получения дробной части числа, у которой возвращаемый результат был бы целым ? ( нужен аналог Паскалевской функции Frac(x), Сишная функция modf не совсем подходит для этого :( )
8.4K
28 апреля 2006 года
Dian
91 / / 18.02.2006
 
Код:
Число - Floor(Число)
1.9K
28 апреля 2006 года
Nigger
71 / / 09.04.2005
Цитата:
Originally posted by Dian
 
Код:
Число - Floor(Число)


Тоже самое делается командой modf ,но мне надо чтобы результат был не дробным( например, от числа 123.45 получить 45.0)

385
28 апреля 2006 года
SomewherSomehow
477 / / 25.07.2004
Цитата:
Originally posted by Nigger
Тоже самое делается командой modf ,но мне надо чтобы результат был не дробным( например, от числа 123.45 получить 45.0)



А что мешает умножить этот результат на 10*кол-во знаков_после_запятой? Или умножаем в цикле, на каждой итерации на 10, пока дробная часть от результата умножения не будет 0 (только еще желательно поставить в цикле условие на кол-во разрядов, чтобы не было переполнения, мало ли что =), или преобразовать в строку, найти точку, взять все что будет после этого символа (только и тут есть подводный камень, в региональных установках Винды(если приложение под винду) задается символ разделитель,какой угодно кроме чисел, соответсвенно надо получить этот символ ну или если лениво, то считать разделителм любой символ кроме цифры)

1.9K
28 апреля 2006 года
Nigger
71 / / 09.04.2005
Мешает вот что :

#define frac(num,i) i*(num/i - floor(num/i))

При использовании этого макроса все нормально работает если i >=1000 . Однако при i = 100 (например num = 1976528) возвращает 27.(9) , при i =10 - 7,(9).
Откуда берется эта погрешность, не пойму :(
(Приложение под ДОС.)
385
28 апреля 2006 года
SomewherSomehow
477 / / 25.07.2004
Цитата:
Originally posted by Nigger
Мешает вот что :

#define frac(num,i) i*(num/i - floor(num/i))

При использовании этого макроса все нормально работает если i >=1000 . Однако при i = 100 (например num = 1976528) возвращает 27.(9) , при i =10 - 7,(9).
Откуда берется эта погрешность, не пойму :(
(Приложение под ДОС.)



Ну это известно откуда, компьютер же не точный теоретический-математический автомат, в силу своей физической природы, имеет ограниченное число разрядов для представления переменной, особенно остро это проявляется при работе с плавающей точкой, особенно в языках разрешающих неявные преобразования типов. Например что как ты думаешь выведет МессаджБокс?

 
Код:
float b = 10;
float a = 91;
float c = a/b;
MessageBox(NULL,FloatToStr(c).c_str(),"",MB_OK);

Вовсе не 9.1...а 9.100000000что-нибудь-невнятное.
Причем такие казусы возможны не только при делении...например что выведет МессаджБокс?
 
Код:
float b = 100000.0000000001;
float a = 200000.0000000001;
float c = a+b;
MessageBox(NULL,FloatToStr(c).c_str(),"",MB_OK);

Вовсе не 300000.0000000002,а просто 300000.
Вообщеем разберись с типами. Подсказка:
 
Код:
float b = 10;
float a = 91;
double c = a/b;
MessageBox(NULL,FloatToStr(c).c_str(),"",MB_OK);

- выведет то что нужно без всяких погрешностей...
385
28 апреля 2006 года
SomewherSomehow
477 / / 25.07.2004
Цитата:
Originally posted by Nigger
Мешает вот что :

#define frac(num,i) (i)*(num/i - floor(num/i))

При использовании этого макроса все нормально работает если i >=1000 . Однако при i = 100 (например num = 1976528) возвращает 27.(9) , при i =10 - 7,(9).
Откуда берется эта погрешность, не пойму :(
(Приложение под ДОС.)



Кстати дополню. О вреде макросов =)
Ты уж меня извини за резкость, но я скажу правду. Макрос, написан безобразно. Если бы я увидел такое в коде коммерческой системы - немедленно бы "оценил" программиста который этот код писал...
Причем, написан не просто безобразно, а не правильно (хотя с виду кажется правильно, а как известно ошибки которые с первого взгляда неочевидны, приносят намного больше вреда чем очевидные).

Дабы не быть голословным.
1) Коли пишешь такой макрос - помни что компилятор "втупую" подставляет значения, и "параметры " которые "передаются" в макрос не вычисляются как если бы передавались в функцию. Поясню на твоем примере:
Все привыкли использовать функции, и такой код не вызовет ни у кого сомнения что используется функция (даже ты сам, автор кода, можешь забыть про то, что это макрос)

 
Код:
float i = 100;
float extend_precision = 10;
float num = 12345678;

float c = frac(some_var,i*extend_precision);

По идее, как рассуждает любой программист который видит этот код. считается дробная часть числа num у которой увеличена точность на один порядок(т.е. сначала i умножается на extend_precision, а потмо передается в функцию, некоторые даже наивно полагают что "передается в макрос", если знают что это макрос =)) ). ожидаем результат 678. но результат на самом деле:
800. Почему? Становится понятным почему если посмотреть на действия компилятора. Он заменяет твой макрос на написанное тобой же выражение, в итоге: float c = 100*10*(12345678/100*10 - floor(12345678/100*10). Порядок действий ясен? Порядок вычисления - вовсе не тот какой казался программисту.
Поэтому рекомендую! Если уж пишете макросы, заключайте каждый аргумент в скобки! Вот так будет более менее:
 
Код:
#define frac(num,i) (i)*((num)/(i) - floor((num)/(i)))
.
Но самое смешное, это тоже не верно, точнее верно не всегда. Итак.
2) Представь что программа довольно объемна...ты помнишь какого типа у тебя каждая переменная, в каждом участке кода, где используется макрос, и что это макрос а не функция. Даже если это помнишь когда разрабатываешь программу - через месяц примерно про такие тонкости забываешь (хотя если программа "боевая", т.е. используется, с первого раза ее нельзя сделать, все-время приходится дорабатывать). Так вот, попробуй передай в свой макрос те же значения, только объяви их так
int i = 100;
int num = 12345678;
т.е. целыми (конечно когда это явно указывается сейчас в примере - закрадываются подозрения в том что пример высосан из пальца, но в реальном коде - про тип переменных забывают сплошь и рядом). Увидишь что макрос вернет 0.
Итог: Опасня это штукак - макросы. Не даром многие советуют обходиться без них. Подумай о том чтобы заменить макрос на функцию.
1.9K
28 апреля 2006 года
Nigger
71 / / 09.04.2005
Спасибо за информацию.
Попробую результат записывать в long double , хотя это не есть хорошо :(
385
28 апреля 2006 года
SomewherSomehow
477 / / 25.07.2004
Цитата:
Originally posted by Nigger
Спасибо за информацию.
Попробую результат записывать в long double , хотя это не есть хорошо :(



Кстати, некоторые вумные люди, в частности разработчики высокоуровневых языков, например c#, давно уже написали класс "money", в котором инкапсулировали, все сложности работы с дробями, при этом ограничив точность, по-моему, двумя цифрами после запятой...Ничего не мешает тебе последовать их примеру и вооружившись мощным инструментарием с++ - создать свой класс, задав необходимую точность... Работать конечно будет медленнее, но кого это волнует при современных мощностях. Хотя конечно если на первом месте стоит быстродействие - используй встроенные типы, а еще лучше пиши на асме =) (хотя асм написанный юзером - и компилятором, часто отличается более высокой производительностью в сторону последнего, как свидетельствуют многочисленные публикации...и я склонен им верить =) )

1.8K
29 апреля 2006 года
k3Eahn
365 / / 19.12.2005
Цитата:
Originally posted by SomewherSomehow
(хотя асм написанный юзером - и компилятором, часто отличается более высокой производительностью в сторону последнего, как свидетельствуют многочисленные публикации...и я склонен им верить =) )


А можете, пжалста, ссылочку на енти самыя публикации кинуть:)

385
29 апреля 2006 года
SomewherSomehow
477 / / 25.07.2004
Цитата:
Originally posted by k3Eahn
А можете, пжалста, ссылочку на енти самыя публикации кинуть:)



Понимаю что свои заявления надо всегда аргументировать, но не всегда это возможно сделать. Т.к. читая книги, журналы, форумы - только редкие маньяки скапливают все материалы в подшивку и потом ими бравируют, в основном люди откладывают у себя в памяти нужную инфу не обременяя ее ссылками. Но я все же приведу вам надежный источник (один из многих, дургие - я просто не могу вспомнить названия, но они все говорят одно и то же, и, т.к. это последняя публикация, которуюя я читал,и где затрагивалась эта тема, то приведу ее) - не поленитесь (кстати призываю всех программситов которые хоят повысить культуру программирования) - почитайте книгу Code Complete. Автор Стив Макконел. Издана на русском в серии Microsoft Press издательством Питер, под названием Совершенный код. Очень Полезная книга, это не реклама - просто совет. Читается (если вы действительно интересуетесь программированием) - как бестселлер, запоем, можно потом использовать в качестве справочника. п.с. самая дорогоая книга в мой жизни - потратил на нее 840 рублей. Так вот.К теме. Почитайте там раздел "оптимизация", узнаете много интересного, в том числе и про ассемблер. =)

385
29 апреля 2006 года
SomewherSomehow
477 / / 25.07.2004
И не нужно думать что вот я почитал - поверил. =) И это едеинственный источник. Есть у меня знакомые работающие с микроконтроллерами (сам по-идее я по специальности тоже должен с ними работать) =), которые тоже в один голос утверждают, что писать лучше на си, при этом самое главное найти соответствующий транслятор... не могу оценить их правоту, тк.к скажу честно с асмом не очень, но вмдя их зарплаты - почему-то проникаешься уважением =)

А тайны их работы остаются для меня загадкой =)
1.9K
29 апреля 2006 года
Nigger
71 / / 09.04.2005
А у типа "long double" под целую часть отведено всего 32 бита ?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог