
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.86] |
![]() |
|
Страницы: (4) 1 [2] 3 4 все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Eric-S
Тема большая поэтому всё рассказать не получиться. Числа с плавающей точкой состоят из мантиссы и экспоненты. И ещё бывают децентрализованные и нормализованные. Проблема в том что перевод чисел из одной системы счисления в другую идут с ошибками округления. Поэтому тут надо будет ещё аккуратно. А ещё числа бывают двоичные и десятичные. Десятичные конечно редкость. Формат вывода чисел бывает с фиксированной точкой бывает научный (-d.ddd...E+ddd...) Мантиса. Точность мантисы. Точность можно вычислить http://en.wikipedia.org/wiki/Machine_epsil...n_using_C.2B.2B Но гораздо проще воспользоваться константой. В Си есть библиотека констант. std::numeric_limits Но так как константу нельзя записать числами из за погрешности при переводи из одной системы счисления(СС) в другую СС. Поэтому машинную точность определяют через функцию power EpsSingle=power(2,-24); EpsDouble=power(2,-53); Экспонента. Тут уже сказали что будет inf(бесконечность), а не NaN(не число). Пересчёт констант из одной СС в другую. Константы легко пересчитать для разной СС. 2^13=10^x log_10(2^13)=x Или x=log(2^13)/log(10) Что касается ловли ошибок. У чисел с плавающей точкой есть разные классы ошибок. http://www.openwatcom.org/index.php/Math_e...handling_on_x87 http://msdn.microsoft.com/en-us/library/wi...9(v=vs.85).aspx Тип ошибок который стоит обрабатывать надо просто установить. http://msdn.microsoft.com/en-us/library/c9...6h(VS.100).aspx По умолчанию насколько помню включено деления на 0 и неправильная команда. Некоторые графические библиотеки любят работать с определённым типом чисел нормированные/денормальными. По поводу общей концепции обработки ошибок. Такого описания я не видел. В численных методах есть два движение. 1. Безошибочные вычисления. 2. Устойчивые к ошибкам вычисления. Без ошибочные вычисления. Для предотвращения переполнения используют длинных числа. Вместо десятичный дробей используют рациональных числа. В базах данных для финансовых вычислений все исчисления идут с 10 числами без конвертации в двоичные. Стив Макконел даёт эту тему тоже в сколь. Хотя общие рекомендации такие. 1. Проверка входных и выходных параметров функции. 2. Выделения памяти в общем коде и передачу обработчику уже выделенного диапазона памяти. 3. Сообщения результата о ошибке ниже следующему обработчику для принятия решения. Лично мне результат ошибки нравиться передавать через return, а не вызывать исключение. |
Сообщ.
#17
,
|
|
|
Утверждать и настаивать не буду. Просто, мне казалось, что она компиляторо и платформозависимая. Конечно же. Ведь компьютер бинарный. Моё удивление происходило из того, что я , как-то не подумал о столь очевидном факте. Точнее, даже и не задумывался. Цитата simsergey @ Если я Вас не так понял, мб переформулируете, или другой приведете пример, что же должна делать функция.. ![]() Отдельный момент, который всплыл при обсуждении, вы поняли правильно. И ваш вариант со структурой, мне гораздо удобнее, чем функция frexp(). А конкретная функция, должна возвращать число разрядов, которые поместятся в мантиссу без усечения. Если мантисса точностью 52 бита, то в двоичной системе, это 52 разряда. Но в 16-ричной это 13 разрядов. А функция должна вернуть число разрядов мантиссы, для системы счисления, с основанием b. |
Сообщ.
#18
,
|
|
|
Цитата Eric-S @ Насколько я знаю, эта структура, может изменятся. Есть даже функции для изменения точности. Структура может изменяться. Но на самом деле есть стандарт IEEE-754 который и был принят для того чтобы числа не изменялись и на разных архитектура имели одинаковый формат. Что касается функции изменения точности, так она только зануляет лишние биты из числ в формате IEEE-754. Так что ей пользоваться не стоит. Вообщем она устаревшая. И такой было чуть ли не во время создания Си. |
Сообщ.
#19
,
|
|
|
Цитата Pavia @ Числа с плавающей точкой состоят из мантиссы и экспоненты. Ага, я это уже давно знаю. Выше, даже приведена структура представления в памяти. Цитата Pavia @ И ещё бывают децентрализованные и нормализованные. Об этом только слышал. Что за зверь, не представляю. Цитата Pavia @ Проблема в том что перевод чисел из одной системы счисления в другую идут с ошибками округления. Поэтому тут надо будет ещё аккуратно. Ну, это известная проблема. В прочем она решаемая. Я собственно уже давно сделал класс для конвертации числа с плавающей точкой в строку, причём с указанной системой счисления. С округлением, действительно, пришлось туго. Но уже всё норм. А вот сейчас, хотел к нему прикрутить дополнительные плюшки. Чтоб лимит знаков, выставлялся автоматически. Дополнительный параметр, раздражает. Цитата Pavia @ А ещё числа бывают двоичные и десятичные. Десятичные конечно редкость. Шутите? Угу... Я так и подумал! Знаем, конечно же, и постоянно пользуемся. двоичная и шестнадцатеричная для компа, десятичная для денег, 12 и 24 для часов, 7 ричная для дней недели... И с основанием n, для прикола. Цитата Pavia @ Формат вывода чисел бывает с фиксированной точкой бывает научный (-d.ddd...E+ddd...) Угу. Знаемс тоже. Кстати, давно мучит вопрос, а как в экспоненциальной записи, оформить 16-ричное число? Или научная исключительно для 10-ричной? Это, если конечно же не использовать специальный значок юникода, а писать латинскую e. Цитата Pavia @ Мантиса. Точность мантисы. Точность можно вычислить http://en.wikipedia.org/wiki/Machine_epsil...n_using_C.2B.2B Но гораздо проще воспользоваться константой. В Си есть библиотека констант. std::numeric_limits Но так как константу нельзя записать числами из за погрешности при переводи из одной системы счисления(СС) в другую СС. Поэтому машинную точность определяют через функцию power EpsSingle=power(2,-24); EpsDouble=power(2,-53); Опс... Это интересно... Так, побегу читать. |
Сообщ.
#20
,
|
|
|
Цитата Eric-S @ Это, если конечно же не использовать специальный значок юникода, а писать латинскую e. Видел используют e махонькую для отделения экспоненты. А в числах там буквы все большие. А вообще тоже интересно общепринятый формат. Добавлено Цитата Eric-S @ Шутите? Угу... Я так и подумал! Знаем, конечно же, и постоянно пользуемся. двоичная и шестнадцатеричная для компа, десятичная для денег, 12 и 24 для часов, 7 ричная для дней недели... И с основанием n, для прикола. В VAX компьютерах была десятичная арифметика реализована прямо в процессоре. |
Сообщ.
#21
,
|
|
|
О! Кажись нашел интересненькое. с std::numeric_limits я уже знаком, но там чего-то не то. Особенно у старого vs 2010.
А вот константа DBL_MANT_DIG возвращает размер мантиссы, для типа long double. Если я конечно правильно понял. И это число, у меня 53. Ха-эм. Ладно, вычтем битик, на знак. Ладненько, теперь надо подумать, как его пересчитать для нужной системы счисления. Для 2-ичной, я разделил на 1, для 16 ричной, я разделил на 4. Но забавно, для 10, я тоже должен разделить на 4 и получить 13. Тогда как точно знаю, что у меня влазит 16 разрядов. |
Сообщ.
#22
,
|
|
|
Цитата Eric-S @ Но забавно, для 10, я тоже должен разделить на 4 и получить 13. Тогда как точно знаю, что у меня влазит 16 разрядов. Не делить. Я же привел пример считаешь через логарифмы а потом округляешь. На само деле все 17 разрядов. |
Сообщ.
#23
,
|
|
|
Цитата Pavia @ Поэтому машинную точность определяют через функцию power EpsSingle=power(2,-24); EpsDouble=power(2,-53); ... Пересчёт констант из одной СС в другую. Константы легко пересчитать для разной СС. 2^13=10^x log_10(2^13)=x Или x=log(2^13)/log(10) Верно. Я же побежал проверять и не дочитал. Но, ха-эм... с функциями непонятки, кто из них кто? Да и математику, давно уж забыл. Сейчас со скрипом вспоминал, что вообще такое логарифм. А уж какими функциями возводить число в степень или искать логарифм, никогда и не ведал. Значит power() это возведение a, в степень b? А log() это логарифм... Упс, а у него один параметр? Не, надо лезть в справочник. Не знал не знал и забыл. |
Сообщ.
#24
,
|
|
|
А разве порядок не выясняется через (int)(double >> 52)? (сейчас не проверю)
С мантиссой в моей Double как Integer разобрались... |
Сообщ.
#25
,
|
|
|
Eric-S
Цитата Eric-S @ Значит power() это возведение a, в степень b? А log() это логарифм... Упс, а у него один параметр? power возведение в степень. Всё верно. Логарифм да. Цитата Eric-S @ Не, надо лезть в справочник. Не знал не знал и забыл. Также уже забыл. Насколько помню log - логарифм по основанию 10, ln - натуральный логарифм, другими словами логарифм по основанию e=2.78.. По поводу логарифма по произвольному основанию надо посмотреть справку в модуле math должно быть что-то. Но можно реализовать и самому через log или ln или через логарифм с любым основанием. log(x)/log(b) где b основание. ln(x)/ln(b) где b основание. |
Сообщ.
#26
,
|
|
|
Pavia, благодарю! у меня получилось.
|
Сообщ.
#27
,
|
|
|
Цитата Pavia @ Но можно реализовать и самому через log или ln или через логарифм с любым основанием. log(x)/log(b) где b основание. ln(x)/ln(b) где b основание. Круто. Это уже выходит за рамки моих знаний. Но оно работает. Спасибо. Цитата Pavia @ На самом деле все 17 разрядов. Ха-эм. На практике у меня 16. Если ставлю 17, то начинаются жуткие проблемы с округлением. Например в последнем разряде, появляются артефакты. А вот написанная функция говорит, что 15. Я правда ткнул мантиссу 52 бита. ![]() ![]() #include <cmath> #include <iostream> int main() { // основание системы счисления int b = 10; // размер мантиссы auto m = std::pow( 2.0, LDBL_MANT_DIG - 1 ); // число разрядов auto d = std::log( m ) / std::log( static_cast< long double >( b ) ); std::cout << "digits: " << d << std::endl; return 0; } Добавлено Вот получившаяся функция. ![]() ![]() // возвращает максимальное число разрядов для указанной системы счисления std::size_t get_digits_count( unsigned int b ) { // число разрядов return static_cast< std::size_t >( std::log( std::pow( 2.0, LDBL_MANT_DIG - 1 ) ) / std::log( static_cast< long double >( b ) ) ); } Это альтернативное решение, не касающееся сабжа. А если вернутся к переполнению, то можно проверять, сравнивая число с максимально допустимым значением std::pow( 2.0, LDBL_MANT_DIG - 1 ). Всем спасибо. Тему закрываю. |
Сообщ.
#28
,
|
|
|
Цитата Pavia @ У вас смесь из математики и программирования. Дела таковы:Насколько помню log - логарифм по основанию 10, ln - натуральный логарифм, другими словами логарифм по основанию e=2.78.. Математика: ln-натуральный, log-общий Программирование: log-натуральный, ln-нет такого (букв мало?) |
Сообщ.
#29
,
|
|
|
Цитата Славян @ Цитата Pavia @ У вас смесь из математики и программирования. Дела таковы:Насколько помню log - логарифм по основанию 10, ln - натуральный логарифм, другими словами логарифм по основанию e=2.78.. Математика: ln-натуральный, log-общий Программирование: log-натуральный, ln-нет такого (букв мало?) С какой-то радости, математику смешивают с программированием? Это уже давно, две разные науки. Лично мне, функциями понятнее. Даже если я тех функций не знаю. Но по контексту можно догадатся. А вот матзначки, вынесут мой несчастный мозг... |
Сообщ.
#30
,
|
|
|
Цитата Eric-S @ Это сильно завязанные науки. Вот log знают все, это общее, это даже начало слова. Но математикам лень использовать общий логарифм, потому они и ввели ln-для натурального (мега-сокращение,да!?), а lg-для десятичного. А вот программистам две буквы - ну уж слижком коротко (в ассемблере и то - редкость), а логарифм нужен. Потому и решили, что пусть log-натуральный, а log10 - десятичный. С какой-то радости, математику смешивают с программированием? Это уже давно, две разные науки. |