NormalizeDouble - а он работает? - страница 2

 
Dmitriy Voevodkin:

Я прошу его округлить double до 2 разряда включительно, а он выдаёт 17-и разрядное число.

И в чём тогда глубокий смысл оператора NormalizeDouble, если он не способен выполнить заявленную функцию?

Не поленитесь, прочитайте то, что я сбросил в предыдущем сообщении. Если поймете, о чем речь - вопросы отпадут.
 
Dmitriy Voevodkin:

Я прошу его округлить double до 2 разряда включительно, а он выдаёт 17-и разрядное число.

И в чём тогда глубокий смысл оператора NormalizeDouble, если он не способен выполнить заявленную функцию?

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

То есть отобразить число можно было и без предварительного использования NormalizeDouble(). При вычислениях же нужно использовать NormalizeDouble() или, если требуется сравнение чисел, то сравнивать абсолютную разность чисел с неким числом заданной точности (наибольшая точность - DBL_EPSILON). 

 
Dmitriy Voevodkin:

вы хотите сказать, что есть сложности в 64-х битах сохранить 0,07 без искажений?

я сейчас не обсуждаю 1/3. Сейчас проблема именно в числе 0,07.

а чем 7/100 отличаются от 1/3?

Чтобы точно сохранять дроби, нужно хранить данные и делать расчеты, только в дробях, а не в этих ваших бинарных системах.

Рациональные числа, которые не могут быть представлены в виде дроби со знаменателем, являющимся степенью двойки, не могут быть точно представлены в виде конечной двоичной дроби, а, значит, не могут быть в точности представлены в памяти компьютера. 

https://pythoner.name/documentation/tutorial/floatingpoint
 
Ihor Herasko:

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

То есть отобразить число можно было и без предварительного использования NormalizeDouble(). При вычислениях же нужно использовать NormalizeDouble() или, если требуется сравнение чисел, то сравнивать абсолютную разность чисел с неким числом заданной точности (наибольшая точность - DBL_EPSILON). 

Так в этом и вопрос. Нормализованные переменные друг с другом сравнивать нельзя, выводить на печать нормализованные переменные нельзя. Зачем она тогда нужна? (нельзя в смысле бессмысленно)

Использовать нормализацию переменной, чтобы после заданных разрядов получить нули, а в конце всё равно 1? Зачем?

а-б > 0,00... и выбирай точность сравнения без бесполезной траты тактов.

Арифметические действия? Так там нормализация тоже ничего не даст.

Получается в целях оптимизации нормализация несёт только вред.

Или покажите хотя бы один конкретный пример, где она хотя бы безвредна.

 
Taras Slobodyanik:

а чем 7/100 отличаются от 1/3?

тем что 1/3 это периодическая дробь, а 7/100 это 7*10-2

 
Dmitriy Voevodkin:

Так в этом и вопрос. Нормализованные переменные друг с другом сравнивать нельзя, выводить на печать нормализованные переменные нельзя. Зачем она тогда нужна? (нельзя в смысле бессмысленно)

Использовать нормализацию переменной, чтобы после заданных разрядов получить нули, а в конце всё равно 1? Зачем?

а-б > 0,00... и выбирай точность сравнения без бесполезной траты тактов.

Арифметические действия? Так там нормализация тоже ничего не даст.

Получается в целях оптимизации нормализация несёт только вред.

Или покажите хотя бы один конкретный пример, где она хотя бы безвредна.

Print(DoubleToString(NormalizeDouble(5.63, 1), 2));

Получим 5.60.

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

DoubleToString() - для вывода нужного количества цифр после запятой.

 
Ihor Herasko:

Получим 5.60.

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

DoubleToString() - для вывода нужного количества цифр после запятой.

Вы привели пример бесполезного кода. Если вы нормализуете до 1 разряда, то и печатать можно по 1 разряду. Эстетику отбросим как не функциональную часть (типа нолик для красоты можно по разному нарисовать).

В данном примере можно сделать с тем же результатом 

Print(DoubleToString(5.63, 1));

Получим те же 5.6

Где на практике нужна нормализация?

 
Dmitriy Voevodkin:

Вы привели пример бесполезного кода. Если вы нормализуете до 1 разряда, то и печатать можно по 1 разряду. Эстетику отбросим как не функциональную часть (типа нолик для красоты можно по разному нарисовать).

В данном примере можно сделать с тем же результатом 

Получим те же 5.6

Где на практике нужна нормализация?

Вам же сказали - округление, не доходит что-ли? Перечитайте. было 5,63 стало 5,60. Не надо? ну ладно, идите дальше.

 
Dmitriy Voevodkin:

Нормализованные переменные друг с другом сравнивать нельзя

Почему это?

 
Dmitriy Voevodkin:

Использовать нормализацию переменной, чтобы после заданных разрядов получить нули, а в конце всё равно 1? Зачем?


Вы вообще понимаете разницу между двоичным и десятичным представлением числа?