Как получить дробную часть числа ?
Тоже самое делается командой modf ,но мне надо чтобы результат был не дробным( например, от числа 123.45 получить 45.0)
Тоже самое делается командой modf ,но мне надо чтобы результат был не дробным( например, от числа 123.45 получить 45.0)
А что мешает умножить этот результат на 10*кол-во знаков_после_запятой? Или умножаем в цикле, на каждой итерации на 10, пока дробная часть от результата умножения не будет 0 (только еще желательно поставить в цикле условие на кол-во разрядов, чтобы не было переполнения, мало ли что =), или преобразовать в строку, найти точку, взять все что будет после этого символа (только и тут есть подводный камень, в региональных установках Винды(если приложение под винду) задается символ разделитель,какой угодно кроме чисел, соответсвенно надо получить этот символ ну или если лениво, то считать разделителм любой символ кроме цифры)
#define frac(num,i) i*(num/i - floor(num/i))
При использовании этого макроса все нормально работает если i >=1000 . Однако при i = 100 (например num = 1976528) возвращает 27.(9) , при i =10 - 7,(9).
Откуда берется эта погрешность, не пойму :(
(Приложение под ДОС.)
Мешает вот что :
#define frac(num,i) i*(num/i - floor(num/i))
При использовании этого макроса все нормально работает если i >=1000 . Однако при i = 100 (например num = 1976528) возвращает 27.(9) , при i =10 - 7,(9).
Откуда берется эта погрешность, не пойму :(
(Приложение под ДОС.)
Ну это известно откуда, компьютер же не точный теоретический-математический автомат, в силу своей физической природы, имеет ограниченное число разрядов для представления переменной, особенно остро это проявляется при работе с плавающей точкой, особенно в языках разрешающих неявные преобразования типов. Например что как ты думаешь выведет МессаджБокс?
float a = 91;
float c = a/b;
MessageBox(NULL,FloatToStr(c).c_str(),"",MB_OK);
Вовсе не 9.1...а 9.100000000что-нибудь-невнятное.
Причем такие казусы возможны не только при делении...например что выведет МессаджБокс?
float a = 200000.0000000001;
float c = a+b;
MessageBox(NULL,FloatToStr(c).c_str(),"",MB_OK);
Вовсе не 300000.0000000002,а просто 300000.
Вообщеем разберись с типами. Подсказка:
float a = 91;
double c = a/b;
MessageBox(NULL,FloatToStr(c).c_str(),"",MB_OK);
- выведет то что нужно без всяких погрешностей...
Мешает вот что :
#define frac(num,i) (i)*(num/i - floor(num/i))
При использовании этого макроса все нормально работает если i >=1000 . Однако при i = 100 (например num = 1976528) возвращает 27.(9) , при i =10 - 7,(9).
Откуда берется эта погрешность, не пойму :(
(Приложение под ДОС.)
Кстати дополню. О вреде макросов =)
Ты уж меня извини за резкость, но я скажу правду. Макрос, написан безобразно. Если бы я увидел такое в коде коммерческой системы - немедленно бы "оценил" программиста который этот код писал...
Причем, написан не просто безобразно, а не правильно (хотя с виду кажется правильно, а как известно ошибки которые с первого взгляда неочевидны, приносят намного больше вреда чем очевидные).
Дабы не быть голословным.
1) Коли пишешь такой макрос - помни что компилятор "втупую" подставляет значения, и "параметры " которые "передаются" в макрос не вычисляются как если бы передавались в функцию. Поясню на твоем примере:
Все привыкли использовать функции, и такой код не вызовет ни у кого сомнения что используется функция (даже ты сам, автор кода, можешь забыть про то, что это макрос)
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). Порядок действий ясен? Порядок вычисления - вовсе не тот какой казался программисту.
Поэтому рекомендую! Если уж пишете макросы, заключайте каждый аргумент в скобки! Вот так будет более менее:
Но самое смешное, это тоже не верно, точнее верно не всегда. Итак.
2) Представь что программа довольно объемна...ты помнишь какого типа у тебя каждая переменная, в каждом участке кода, где используется макрос, и что это макрос а не функция. Даже если это помнишь когда разрабатываешь программу - через месяц примерно про такие тонкости забываешь (хотя если программа "боевая", т.е. используется, с первого раза ее нельзя сделать, все-время приходится дорабатывать). Так вот, попробуй передай в свой макрос те же значения, только объяви их так
int i = 100;
int num = 12345678;
т.е. целыми (конечно когда это явно указывается сейчас в примере - закрадываются подозрения в том что пример высосан из пальца, но в реальном коде - про тип переменных забывают сплошь и рядом). Увидишь что макрос вернет 0.
Итог: Опасня это штукак - макросы. Не даром многие советуют обходиться без них. Подумай о том чтобы заменить макрос на функцию.
Попробую результат записывать в long double , хотя это не есть хорошо :(
Спасибо за информацию.
Попробую результат записывать в long double , хотя это не есть хорошо :(
Кстати, некоторые вумные люди, в частности разработчики высокоуровневых языков, например c#, давно уже написали класс "money", в котором инкапсулировали, все сложности работы с дробями, при этом ограничив точность, по-моему, двумя цифрами после запятой...Ничего не мешает тебе последовать их примеру и вооружившись мощным инструментарием с++ - создать свой класс, задав необходимую точность... Работать конечно будет медленнее, но кого это волнует при современных мощностях. Хотя конечно если на первом месте стоит быстродействие - используй встроенные типы, а еще лучше пиши на асме =) (хотя асм написанный юзером - и компилятором, часто отличается более высокой производительностью в сторону последнего, как свидетельствуют многочисленные публикации...и я склонен им верить =) )
(хотя асм написанный юзером - и компилятором, часто отличается более высокой производительностью в сторону последнего, как свидетельствуют многочисленные публикации...и я склонен им верить =) )
А можете, пжалста, ссылочку на енти самыя публикации кинуть:)
А можете, пжалста, ссылочку на енти самыя публикации кинуть:)
Понимаю что свои заявления надо всегда аргументировать, но не всегда это возможно сделать. Т.к. читая книги, журналы, форумы - только редкие маньяки скапливают все материалы в подшивку и потом ими бравируют, в основном люди откладывают у себя в памяти нужную инфу не обременяя ее ссылками. Но я все же приведу вам надежный источник (один из многих, дургие - я просто не могу вспомнить названия, но они все говорят одно и то же, и, т.к. это последняя публикация, которуюя я читал,и где затрагивалась эта тема, то приведу ее) - не поленитесь (кстати призываю всех программситов которые хоят повысить культуру программирования) - почитайте книгу Code Complete. Автор Стив Макконел. Издана на русском в серии Microsoft Press издательством Питер, под названием Совершенный код. Очень Полезная книга, это не реклама - просто совет. Читается (если вы действительно интересуетесь программированием) - как бестселлер, запоем, можно потом использовать в качестве справочника. п.с. самая дорогоая книга в мой жизни - потратил на нее 840 рублей. Так вот.К теме. Почитайте там раздел "оптимизация", узнаете много интересного, в том числе и про ассемблер. =)
А тайны их работы остаются для меня загадкой =)