2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3  След.
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 15:04 


14/06/15
144
Dmitriy40 в сообщении #1196167 писал(а):
Попробую ответить на 4-5 пункты.
Для того чтобы сложить два числа с плавающей точкой процессор (а не Java) сдвигает одно из них (у которого показатель степени меньше) вправо с увеличением показателя степени на 1 до сравнивания показателей степени, получатся числа (в скобках указываю подразумеваемые биты мантиссы, подчёркивание отделяет 52 бита мантиссы):
7.5708 = 0 10000000001 (1).111001001000011111111100101110010010001110100010101 (Inexact, 1+11+52 bit = 64 bit)
3.7854 = 0 10000000001 (0).111100100100001111111110010111001001000111010001010_1 (Inexact, 1+11+52 bit = 64 bit)
Теперь уже можно их складывать (мантиссы), сумма будет равна:
11.3562 = 0 10000000001 (10).110101101100101111111011000101011011010101110011111_1
Возникло переполнение мантиссы, для нормализации числа мантисса сдвигается вправо с увеличением показателя степени:
11.3562 = 0 10000000010 (01).011010110110010111111101100010101101101010111001111_11
Теперь нужно округлить число до представимого мантиссой, т.к. отбрасываемые биты = 11, то к младшему биту мантиссы добавляется 1, а все биты правее отбрасываются:
11.3562 = 0 10000000010 (01).011010110110010111111101100010101101101010111010000
Это число соответствует числу 11.35620000000000118234311230480670928955078125, но точные из них лишь выделенные жирным цифры. Остальные не равны нулю из-за нехватки 52-х битов мантиссы для более точного представления чисел.

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


Раз Вы уже коснулись темы округления то я бы хотел для начала более подробно проконсультироваться у вас по поводу первых трех моих вопросов c моими доп. объяснениями:

1. Как Java преобраз. эти значения в двоич? С этим более менее мне понятно:

7.5708 = 0 10000000001 1110010010000111111111001011100100100011101000101010 (Inexact, 1+11+52 bit = 64 bit)

3.7854 = 0 10000000000 1110010010000111111111001011100100100011101000101010 (Inexact, 1+11+52 bit = 64 bit)

За исключением того, что это уже округленные значения.

2. Какое представление этого двоичн. ( 80 или 64 бит длины)?

Понятно что в конечном итоге буде 64 битное представление указанное выше, но перед тем как оно будет java перекидывает десятичное значение в 80 битное (или даже больше, не знаю точно какое) двоичное представление, а затем округляет его методом Java has Round-Half-Even (Banker's Rounding) но как он пошагово действует я не понимаю , может быть вы знаете?

3. Как Java округл. этот двоич. (7.5708 and 3.7854 не могут точно быть преобразованы в двоичн., java округляет их в последнем или нескольких последних битах)?

Хотелось бы ваших более подробных комментариев по моим первым 3 вопросам.

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 15:37 
Заслуженный участник


26/05/14
981
Java следует IEEE 754 (https://en.wikipedia.org/wiki/IEEE_floating_point).
Числа до и после любых операций представляются в формате 64 бит.
Стандарт описывает операцию сложения очень просто: результат должен быть 64 бит и должен быть как можно ближе точному результату сложения двух исходных чисел. Если таких самых близких значений два, то применяется округление https://en.wikipedia.org/wiki/Rounding#Round_half_to_even.
Тоже правило применяется к преобразованию десятичного литерала в двоичное представление - выбирается значение ближайшее к точному.

Я не совсем прав про 64 бита: https://en.wikipedia.org/wiki/Strictfp. Компилятору можно использовать повышенную точность, но вы эту возможность не контролируете (но можете её отключить).
Использование расширенной арифметики может принести как плоды (повышенную точность), так и неприятности (вы два раза исполняете один код и получаете разные результаты).

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 15:44 
Заслуженный участник
Аватара пользователя


16/07/14
8346
Цюрих
sashatgu, подробный комментарий, как это всё происходит - http://grepcode.com/file/repository.gre ... .java#1254 (исходный код, конвертирующий десятичное представление в double) [важно: я не уверен, что во всех реализациях код эквивалентный].

Dmitriy40 в сообщении #1196167 писал(а):
там появляется единичка - не знаю.
Потому что нигде не запоминается, какие цифры точны.
Dmitriy40 в сообщении #1196167 писал(а):
Почему Java выводит лишнюю цифру после запятой
Потому что вывод с вашими настройками выводит выводит достаточное число разрядов, чтобы дойти до ошибочных (как именно выводится - не знаю, надо либо читать документацию, либо смотреть исходники).

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 16:17 
Заслуженный участник


20/08/14
11063
Россия, Москва
sashatgu
Я не могу подробно ответить именно про Java, потому что ей не владею, но в любом случае преобразования делает процессор аппаратно и вот по нему я могу что-то рассказать.
Преобразование из десятичного вида в двоичный идёт поцифирно, к промежуточному результату добавляется каждая десятичная цифра. Но и представление промежуточного результата, и каждой десятичной цифры - все двоичные, и потому в какой-то момент десятичная цифра в двоичном представлении становится меньше минимального шага представления чисел в double формате и при сложении двух double чисел происходит округление до ближайшего представимого числа. На этом цикл преобразования числа и завершается т.к. двоичное представление следующей младшей десятичной цифры будет уже гарантированно меньше минимального шага представимых чисел для формата double, т.е при дальшем преобразовании число уже не изменится. Тут могут быть некоторые тонкости, но предлагаю в них не погружаться.
Использует ли Java 80-ми битное представление чисел при преобразовании из десятичной формы в двоичную - я не знаю (но сомневаюсь). В любом случае результат всё равно будет одинаков (можно придумать исключения, но они все будут отличаться не более чем на 1 младший двоичный разряд формата double).

Процессор (а не Java) при операциях с вещественными типами чисел использует не ровно 53 (или 24 или 64) бита мантиссы, а больше, именно для возможности более правильного округления результата. Для 80-ми битных чисел раньше вычислялись 4 лишних бита справа, как для современных процессоров и для 64-х битных чисел не помню. Да это и несущественно, главное что точно известно как именно он округляет числа: есть 4 режима, но почти всегда используют более математически правильный - к ближайшему. Единственное исключение - если отбрасываемые при округлении биты равно строго половине младшего оставляемого разряда, тогда округляется к ближайшему чётному числу, а не к любому ближайшему. Это сделано для уменьшения в среднем погрешности длинных последовательных вычислений.

Вообще достаточно знать что все числа округляются до соответствующей точности (24, 53, 64 бита) к ближайшему представимому числу. Как именно округляется и сколько при этом битов считается - несущественно. Причины появления малопонятных единичек далеко справа или показа 11.3561999999999 - недостаточность количества битов мантиссы выбранного формата для обеспечения ещё лучшей точности. Как там что происходит на уровне битов - лишнее. ;-)

-- 01.03.2017, 16:24 --

mihaild в сообщении #1196251 писал(а):
Dmitriy40 в сообщении #1196167 писал(а):
там появляется единичка - не знаю.
Потому что нигде не запоминается, какие цифры точны.
Это понятно, я не знаю почему Java выводит 17 десятичных цифр, хотя формат double обеспечивает лишь <16 точных цифр, да и то не всегда. Но уж точно никак не 17. Так что выводить 17 цифр - глупость, а при самой левой цифре 2 и более даже и 16 цифр уже не точные (правая должна быть лишь чётной), и т.д.

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 17:10 
Заслуженный участник
Аватара пользователя


16/07/14
8346
Цюрих
Dmitriy40 в сообщении #1196263 писал(а):
но в любом случае преобразования делает процессор аппаратно
Преобразование из десятичной дроби в двоичную и обратно делаются программно.

Dmitriy40 в сообщении #1196263 писал(а):
Это понятно, я не знаю почему Java выводит 17 десятичных цифр, хотя формат double обеспечивает лишь <16 точных цифр
Может и больше, если число хорошее.
Возможно, там вывод устроен так, чтобы результат парсился обратно в ровно то же самое число (но это уже домыслы, в детали парсинга я не вчитывался, а вывод не смотрел вообще).

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 17:59 
Заслуженный участник


20/08/14
11063
Россия, Москва

(Оффтоп)

mihaild в сообщении #1196280 писал(а):
Преобразование из десятичной дроби в двоичную и обратно делаются программно.
Да, немного коряво выразился, я имел в виду что все действия над числами с плавающей запятой выполняет не программа с именем Java побитно/побайтно, а процессор аппаратно и одинаково для любой программы (не считая округлений). Ну и вообще-то есть команды FBLD/FBSTP, загружающая/сохраняющая именно десятичные цифры в/из вещественного числа, но ими вероятно давно не пользуются. Поправить текст уже не могу, поздно.

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 19:37 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Dmitriy40 в сообщении #1196263 писал(а):
Использует ли Java 80-ми битное представление чисел при преобразовании из десятичной формы в двоичную - я не знаю (но сомневаюсь).

80-битное вообще не входит в стандарт IEEE 754, это чисто Intel-овская самодеятельность, причём исчезнувшая со временем даже в самом Intel. Разумеется, Java чисто IEEE 754.

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 19:53 
Заслуженный участник


26/05/14
981
Cтандарт Java не запрещает использовать расширенные типы при вычислениях (https://en.wikipedia.org/wiki/Strictfp):
Цитата:
Since JVM 1.2, intermediate computations are not limited to the standard 32 bit and 64 bit precisions. On platforms that can handle other representations e.g. 80-bit double extended on x86 or x86-64 platforms, those representations can be used, helping to prevent round-off errors and overflows, thereby increasing precision.

То есть Java по умолчанию не следует IEEE 754 буквально.

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 21:24 


14/06/15
144
Большое спасибо за ответы, хотя пока многое не понятно:

1. Можно ли средствами самой Java сделать следующее: перекинуть 2 десятичных числа в двоичные, затем их сложить - найти их сумму в двоичном виде, а затем эту двоичную сумму конвертировать в десятичное число. Причем так чтоб полученный десятичный результат соответствовал тому - который мы бы получи просто сложив 2 десятичных числа в самой java.

2. Все таки не понятно каким образом java конвертирует десятичные числа в двоичные - а затем их округляет - нужны ли java доп. биты для этого или нет.

3. Можно ли конвертацию (дес в двоичн. с округл.) которую проводит java проделать самому на бумаге?

4. До конца не понял какое число java округляет при конвертацции - исходное десятичное или полученное двоичное?

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 21:39 
Заслуженный участник
Аватара пользователя


16/07/14
8346
Цюрих
sashatgu в сообщении #1196335 писал(а):
перекинуть 2 десятичных числа в двоичные
Проблема в том, что, например, $0.2$ не выражается конечной двоичной дробью.
sashatgu в сообщении #1196335 писал(а):
чтоб полученный десятичный результат соответствовал тому - который мы бы получи просто сложив 2 десятичных числа в самой java
В смысле - с использованием неограниченной точности по основанию $10$? Придется для начала сделать свой класс, хранящий рациональные числа неограниченной точности в двоичной арифметике. Не знаю, есть ли такой готовый в стандартной библиотеке - но его, конечно, можно реализовать.
sashatgu в сообщении #1196335 писал(а):
2. Все таки не понятно каким образом java конвертирует десятичные числа в двоичные - а затем их округляет - нужны ли java доп. биты для этого или нет.
Ну посмотрите код, который делает этот перевод. Он довольно сложный, и пересказывать его бессмысленно. Из вещественной арифметики от процессора там требуется только double, но еще используется, скажем, арифметика по основанию $10$ с неограниченной точностью.
sashatgu в сообщении #1196335 писал(а):
До конца не понял какое число java округляет при конвертацции - исходное десятичное или полученное двоичное?
Находится число, ближайшее к исходному десятичному, представимое в double.
sashatgu в сообщении #1196335 писал(а):
3. Можно ли конвертацию (дес в двоичн. с округл.) которую проводит java проделать самому на бумаге?
Можно, конечно. Берете код, делающий эту конвертацию, и строчка за строчкой проводите. Там используется вещественная арифметика от процессора, так что многое придется считать в двоичной системе (и внимательно следить, как именно работают операции), но вполне подъемная задача. Если приложить усилия, а не надеяться, что магическим образом нетривиальные вещи объяснят просто (а переводить код с java на русский - бессмысленно).

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение01.03.2017, 21:41 
Заслуженный участник


26/05/14
981
sashatgu в сообщении #1196335 писал(а):
1. Можно ли средствами самой Java сделать следующее: перекинуть 2 десятичных числа в двоичные, затем их сложить - найти их сумму в двоичном виде, а затем эту двоичную сумму конвертировать в десятичное число. Причем так чтоб полученный десятичный результат соответствовал тому - который мы бы получи просто сложив 2 десятичных числа в самой java.
Это можно сделать средствами Java, но не двоичными числами. Главная трудность - не все десятичные числа точно представимы в двоичном виде. Это значит, что вам всегда надо будет следить точностью. А не так легко. Воспользуйтесь BigDecimal: http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html.

Цитата:
2. Все таки не понятно каким образом java конвертирует десятичные числа в двоичные - а затем их округляет - нужны ли java доп. биты для этого или нет.
Да, дополнительные биты нужны. Есть работы (не могу сейчас отыскать) в которых показывается, что невозможно точно перевести десятичный литерал в двоичную форму без дополнительных разрядов.

Цитата:
3. Можно ли конвертацию (дес в двоичн. с округл.) которую проводит java проделать самому на бумаге?
Да, можно. Найдите набольшую степень двойки, которая не превосходит ваше число. Запишите её. Вычтите её из числа. Продолжайте пока число не станет нулём или пока у вас будет хватать терпения. Те числа что вы выписали - биты двоичного представления числа.

Цитата:
4. До конца не понял какое число java округляет при конвертацции - исходное десятичное или полученное двоичное?
По стандарту Java обязана подобрать такое двоичное число которое ближе всего к вашему десятичному. Что именно делает Java можно прочитать в её исходных кодах: http://download.java.net/openjdk/jdk8/. Предупреждаю, что это потребует времени.

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение05.03.2017, 16:24 


14/06/15
144
mihaild в сообщении #1196137 писал(а):
sashatgu в сообщении #1196132 писал(а):
Ну а какой тогда истинный смысл в $p$, ведь как я понимаю $p$ означает какое то количество знаков после запятой в числах с плавающей запятой.
Есть много разных форматов чисел с плавающей запятой - а именно, каждая четверка $(\beta, p, e_{min}, e_{max})$ задает формат.

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

-- 28.02.2017, 23:06 --

sashatgu в сообщении #1196136 писал(а):
Ведь эта дробь не будет равна 1.
Любой $x \neq 0$ единственным способом представляется в виде $sign(x) \cdot y \cdot \beta^n$, где $y \in [1; \beta)$, а $n$ -целое. И как раз $y = \frac{x}{\beta^{\left \lfloor \log_{\beta}|x|  \right \rfloor }}$.
А скобки - это округление вниз. Но там как раз выписано определение сразу всего выражения
sashatgu в сообщении #1196136 писал(а):
where $\beta^{\left \lfloor \log_{\beta}|x|  \right \rfloor }$ is the largest integer power of $\beta$ smaller than $|x|$


A finite floating-point number in such a format is a number for which there exists at least one representation (M, e) such that:

Изображение

Another way to express the same floating-point number x is by using
the triplet (s, m, e), so that:

Изображение

То есть как я понимаю M - это целое число, а m - дробное число?

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение05.03.2017, 16:51 
Заслуженный участник
Аватара пользователя


16/07/14
8346
Цюрих
sashatgu в сообщении #1197373 писал(а):
То есть как я понимаю M - это целое число
sashatgu в сообщении #1196030 писал(а):
where M is an integer

sashatgu в сообщении #1197373 писал(а):
m - дробное число?
Вы можете явно выписать, как связаны $m$ и $M$? Какие ограничения должны быть на $m$, чтобы два варианта представимости были эквивалентны?
(и я почти уверен, что в вашем источнике строчкой ниже написано, каким должно быть $m$)

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение05.03.2017, 17:02 


14/06/15
144
mihaild в сообщении #1197381 писал(а):
sashatgu в сообщении #1197373 писал(а):
То есть как я понимаю M - это целое число
sashatgu в сообщении #1196030 писал(а):
where M is an integer

sashatgu в сообщении #1197373 писал(а):
m - дробное число?
Вы можете явно выписать, как связаны $m$ и $M$? Какие ограничения должны быть на $m$, чтобы два варианта представимости были эквивалентны?
(и я почти уверен, что в вашем источнике строчкой ниже написано, каким должно быть $m$)



• M is an integer of absolute value less than or equal to (B^p) −1. It is called
the integral significand of the representation of x;
• e is an integer such that emin <= e <= emax, called the exponent of the
representation of x.


x = Изображение

 Профиль  
                  
 
 Re: Помогите разобраться с точностью
Сообщение05.03.2017, 20:22 


14/06/15
144
Объясните плиз эту таблицу и подписи к ней:


Изображение

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 38 ]  На страницу Пред.  1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group