Круглое число
От: кт  
Дата: 26.02.17 14:26
Оценка: 4 (2)
Байки 90-х
Круглое число

За окном начало 90-х. Происходит массовый переход на персональные компьютеры. Для большинства это означает смену всего, включая язык программирования. Для большинства, но все же не для всех. Один мой хороший знакомый вовсе не собирается переписывать свои тексты при уходе с ЕС ЭВМ. Задачи у него вычислительные, довольно объемные. И все его силы уходят на разработку модели, прогоны и анализ результатов. Программирование считает делом второстепенным, просто как правила записи текстов и при этом очень консервативен: написанное однажды старается больше не менять, поскольку, мол, это уже отлажено. Всегда занят кучей дел, поэтому просит меня помочь ему с переносом программ на x86. Для начала добиться, чтобы результаты на EC-1045 и IBM-PC/AT совпадали цифра в цифру.

Хорошо, соглашаюсь я и получаю для сверки кучу распечаток с ЕС. Строгого совпадения сходу не видно и я начинаю последовательно сравнивать промежуточные результаты.
Странное дело! Расхождение начинается в совершенно безобидном месте, там, где вещественное число 4 байта преобразуется в вещественное же, но в 8 байт. Конкретно значение 1.2512Е+00 превращается почему-то 1.25119996070860E+000. А на ЕС это же значение преобразуется в интуитивно ожидаемые 1.25120000000000E+00. Что за черт? Преобразование на персоналке идет через FPU, точнее, тогда в 90-х, еще через отдельный «математический сопроцессор». В него загружается 4-байтное число, а затем оно же «выгружается» обратно в память, но уже как 8-байтное. Так-так. Понятно. В FPU двоичная мантисса просто расширяется нулями. И в таком виде выдается обратно. Но такое «круглое» двоичное число выглядит совсем некруглым в десятичном виде. Интересно, значит, в IBM-360 в свое время все-таки озаботились подгонкой мантиссы под «круглые» десятичные значения?

Объясняю это «заказчику», но он недоволен и не понимает.
— Не должно быть никаких ненулевых цифр в мантиссах. Это же просто другое значение.
— Да нет, погрешность все равно не превышает половины младшего разряда. И вообще выкинул бы ты все вещественные переменные 4 байта. На кой ляд они тебе. И «ошибки» преобразования исчезнут…
— Твое дело – добиться совпадения, а не указывать, как программы менять. Работали они – не тронь!

Ладно, думаю. Поправлю-ка я системную библиотеку в части преобразования. Только вот как нули-то получить, раз сопроцессор отказывается их подбирать? Надо что-нибудь попроще. Например, вот так: перевести число в текст, дописать текстовую строку кучей нулей справа и преобразовать обратно в IEEE-754. Медленно, зато будет точно как у IBM-360. Получилось. Все результаты совпали, «заказчик» остался доволен.

Однако через пару месяцев опять он связь выходит. Слушай, говорит, чего-то программа стала работать заметно медленней. Посмотри. А чего смотреть-то? Ну, вычисления и вычисления. А то, что я преобразования новые добавил, так они всего в паре мест и вне циклов, т.е. по времени неощутимо. Ладно, посмотрю. Глянул – а там чуть не через каждые десять команд те самые преобразования через текст и дописывание нулей. Оказалось, один символ в тексте программы случайно потерли. (Небось, ногтем за «Backspace» зацепили.) И в одном месте в описании вместо DECIMAL FLOAT(16) получился текст DECIMAL FLOAT(6).
Т.е. как раз вместо IEEE-754 8 байт случайно получилось IEEE-754 4 байта. И, конечно же, по закону пакости эта переменная во всех формулах оказалась задействована и везде включился свежеиспеченный алгоритм формирования круглых чисел. Поправили, преобразования исчезли, скорость восстановилась и ЕС-1045 окончательно потеряла одного из своих последних пользователей.

Вопрос, правда, остался. При расширении мантиссы числа с «плавающей» точкой, надо ли делать «круглое» десятичное число? Или достаточно «круглого» двоичного. И почему 50 лет назад в IBM-360 все-таки сделали «круглое» десятичное? С точки зрения погрешности вычислений «круглые» числа ведь ничего не дают. Или все-таки дают?
Re: Круглое число
От: sambl4 Россия  
Дата: 26.02.17 14:48
Оценка:
Здравствуйте, кт, Вы писали:

кт>Вопрос, правда, остался. При расширении мантиссы числа с «плавающей» точкой, надо ли делать «круглое» десятичное число? Или достаточно «круглого» двоичного. И почему 50 лет назад в IBM-360 все-таки сделали «круглое» десятичное? С точки зрения погрешности вычислений «круглые» числа ведь ничего не дают. Или все-таки дают?


Тестеры бывают докапаваются — вводят "круглые" десятичные числа, а потом видите ли значения их пугают
Re: Круглое число
От: pagid Россия  
Дата: 26.02.17 14:49
Оценка:
Здравствуйте, кт, Вы писали:

кт>Вопрос, правда, остался. При расширении мантиссы числа с «плавающей» точкой, надо ли делать «круглое» десятичное число?

Не надо. Но точность в младших разрядах мантиссы интересует не нужно преобразовывать туда-сюда без надобности.

кт> Или достаточно «круглого» двоичного.

Пока 4-байтовым было хватало, значит достаточно. Если не достаточно, то нужно изначально использовать 8-байтовое.

кт> И почему 50 лет назад в IBM-360 все-таки сделали «круглое» десятичное?

Это очень странно. Жаль сейчас не проверить. Но предполагаю, что это не архитектурная IBM-360, а особенность преобразования типов в том применяемом языке. PL/1 ?

кт> С точки зрения погрешности вычислений «круглые» числа ведь ничего не дают. Или все-таки дают?

Этим вопросом нужно задаваться когда принимается решение о разрядности используемых переменных и вычислений пользоваться.
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re: Круглое число
От: Privalov  
Дата: 26.02.17 14:54
Оценка:
Здравствуйте, кт, Вы писали:

кт>И в одном месте в описании вместо DECIMAL FLOAT(16) получился текст DECIMAL FLOAT(6).


А вот у меня при переносе программ с ЕС на PC никаких вычмслительных проблем не возникло. А все потому, что те, кто начинал проект, в качестве основного языка выбрали Фортран. И не ленились писать IMPLICIT DOUBLE PRESIGION везде, где нужно. Причем все нармально работало и в MS DOS, и с DOS-extender-ом, и в Чикаге, и в Полуоси.

кт>Вопрос, правда, остался. При расширении мантиссы числа с «плавающей» точкой, надо ли делать «круглое» десятичное число? Или достаточно «круглого» двоичного. И почему 50 лет назад в IBM-360 все-таки сделали «круглое» десятичное? С точки зрения погрешности вычислений «круглые» числа ведь ничего не дают. Или все-таки дают?


Это о чем? О поддержке DECIMAL FIXED?
Re[2]: Круглое число
От: кт  
Дата: 26.02.17 15:25
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Это о чем? О поддержке DECIMAL FIXED?

Нет, вопрос о том, что должно выдавать FPU после команд
FLD32 X1
FST64 X2
Если X1=1.2512
Почему-то ждут, что 1.25119999999999
А FPU выдает другой результат
Re[2]: Круглое число
От: кт  
Дата: 26.02.17 17:28
Оценка:
Здравствуйте, pagid, Вы писали:

кт>>Вопрос, правда, остался. При расширении мантиссы числа с «плавающей» точкой, надо ли делать «круглое» десятичное число?

P>Не надо.
Я не столь уверен. Получается, у программиста нет способа указать, что мантисса "точная" и он получает представление числа не с минимально возможной погрешностью.
P>Но точность в младших разрядах мантиссы интересует не нужно преобразовывать туда-сюда без надобности.
Это точно. Особенно, когда весь расчет случайно, правда, превратился в одно сплошное преобразование.

кт>> Или достаточно «круглого» двоичного.

P>Пока 4-байтовым было хватало, значит достаточно. Если не достаточно, то нужно изначально использовать 8-байтовое.
Тут речь не совсем об этом. Никто не задумывался, что мантиссу с десятичными нулями FPU просто так, по умолчанию, искать не будет.

кт>> И почему 50 лет назад в IBM-360 все-таки сделали «круглое» десятичное?

P>Это очень странно. Жаль сейчас не проверить. Но предполагаю, что это не архитектурная IBM-360, а особенность преобразования типов в том применяемом языке. PL/1 ?
Возможно не архитектура, но все равно только так. Кстати, у PL/1 и Фортрана расчетная, числовая часть полностью совпадает, точнее все из Фортрана просто перенесено в PL один к одному.

кт>> С точки зрения погрешности вычислений «круглые» числа ведь ничего не дают. Или все-таки дают?

P>Этим вопросом нужно задаваться когда принимается решение о разрядности используемых переменных и вычислений пользоваться.
Ну, хозяин-барин отказался исключать старые типы: дескать, как на ЕС работало — так и надо.
Re[3]: Круглое число
От: pagid Россия  
Дата: 26.02.17 19:05
Оценка:
Здравствуйте, кт, Вы писали:

кт>Я не столь уверен. Получается, у программиста нет способа указать, что мантисса "точная" и он получает представление числа не с минимально возможной погрешностью.

На реальной архитектуре точность же не произвольная, максимум два варианта. Float и double в современных языках это полностью покрывают. А возможность указать "произвольную" точность это еще один косяк PL/1, и в вашем случае он проявился.

Только что заметил. Там на самом деле было DECIMAL FLOAT(16), а не BINARY FLOAT(16)
Тогда все понятно. И почему представление и преобразование было "точным" и почему у вас задачи считались целыми ночь вместо максимальных двух часов.

кт>Ну, хозяин-барин отказался исключать старые типы: дескать, как на ЕС работало — так и надо.

Так изначально не нужно было DECIMAL использовать. А так да, эмулировать его чисто программно на Intel, но и на ЕС он должен был быть в значительной степени программым.
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re: Круглое число
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 26.02.17 19:13
Оценка:
Здравствуйте, кт, Вы писали:

кт>Странное дело! Расхождение начинается в совершенно безобидном месте, там, где вещественное число 4 байта преобразуется в вещественное же, но в 8 байт. Конкретно значение 1.2512Е+00 превращается почему-то 1.25119996070860E+000. А на ЕС это же значение преобразуется в интуитивно ожидаемые 1.25120000000000E+00.


На StackOverflow вопрос "а почему плавучка сломана" с приведением примера типа 0.3 != 0.1 * 3 задаётся в среднем раз в 2 дня. Наверно, это рекордсмен среди тупых вопросов.

И именно для максимальной понятности работы с плавучкой на современных потомках ЕС ЭВМ (в лице zSeries) сделали _аппаратную_ поддержки десятичной плавучки (эта реализация принята в IEEE 754-2008).

кт>Однако через пару месяцев опять он связь выходит. Слушай, говорит, чего-то программа стала работать заметно медленней. Посмотри. А чего смотреть-то? Ну, вычисления и вычисления. А то, что я преобразования новые добавил, так они всего в паре мест и вне циклов, т.е. по времени неощутимо. Ладно, посмотрю. Глянул – а там чуть не через каждые десять команд те самые преобразования через текст и дописывание нулей. Оказалось, один символ в тексте программы случайно потерли. (Небось, ногтем за «Backspace» зацепили.) И в одном месте в описании вместо DECIMAL FLOAT(16) получился текст DECIMAL FLOAT(6).


А как именно работал там DECIMAL FLOAT?
На старой — через BCD арифметику S/360? А то "честным" float там такого нельзя было сделать (там была двоичная плавучка с другими особенностями, но сильно похожая на современную).
На новой — явно же тоже не через обычный float?

кт>Т.е. как раз вместо IEEE-754 8 байт случайно получилось IEEE-754 4 байта.


Точно IEEE754? А то ой сомнительно, судя по описанному.

кт>Вопрос, правда, остался. При расширении мантиссы числа с «плавающей» точкой, надо ли делать «круглое» десятичное число? Или достаточно «круглого» двоичного. И почему 50 лет назад в IBM-360 все-таки сделали «круглое» десятичное? С точки зрения погрешности вычислений «круглые» числа ведь ничего не дают. Или все-таки дают?


В родной плавучке S/360 (той, которая в ассемблерных командах с суффиксом D) не было десятичного режима.
А как работал текстовый импорт — надо уточнять, у меня под рукой нет деталей.
The God is real, unless declared integer.
Re[4]: Круглое число
От: Privalov  
Дата: 26.02.17 19:17
Оценка:
Здравствуйте, pagid, Вы писали:

P>Только что заметил. Там на самом деле было DECIMAL FLOAT(16), а не BINARY FLOAT(16)


BINARY FLOAT(16) — это как-то мало. ЕМНИП, 53 должно быть.

P>Тогда все понятно. И почему представление и преобразование было "точным" и почему у вас задачи считались целыми ночь вместо максимальных двух часов.


В PL/1, ЕМНИП, по умолчанию использовался тип DECIMAL FLOAT. Кроме переменных, имена которых начинались с определенных букв (K, L, M, N, I, J, по-моему). Такие переменные были BINARY FIXED.

Некоторые вообще DECIMAL FIXED в расчетах использовали. И ничего, как-то прокатывало.
Re[2]: Круглое число
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 26.02.17 19:26
Оценка:
Здравствуйте, Privalov, Вы писали:

P>А вот у меня при переносе программ с ЕС на PC никаких вычмслительных проблем не возникло. А все потому, что те, кто начинал проект, в качестве основного языка выбрали Фортран. И не ленились писать IMPLICIT DOUBLE PRESIGION везде, где нужно.


Ну так переход с S/360 double на IEEE754 double был прогрессивен во всём. Больший диапазон порядков (10^308 против 10^76), более аккуратное округление (ширина 56 бит при базе порядка 16 в S/360 давала результаты не лучше, чем ширина 53 бита при базе 2; к тому же арифметика S/360 имела только 1 round bit против 3 — round+guard+sticky в IEEE754, а по умолчанию в FPU вообще extended на 64 бита сохранённой мантиссы).
Вот с single были некоторые проблемы за счёт сокращения диапазона порядков до 10^38, но и то вылазили у редчайших клиентов, а остальные были довольны устойчивыми 24 битами мантиссы, вместо 21-24, как в S/360.

P> Причем все нармально работало и в MS DOS, и с DOS-extender-ом, и в Чикаге, и в Полуоси.


А при чём тут ось? Важнее само наличие FPU, и какие библиотеки используются, если его нет. К MS Фортрану шли режимы fp{i,c}[87], которые гарантированно точные, и fpa, которая быстрая и неточная. Вот с fpa библиотекой можно было иногда получать странноватые результаты — но на наших тогдашних XT и AT/286 без FPU это было всё равно хорошо.
The God is real, unless declared integer.
Re[5]: Круглое число
От: pagid Россия  
Дата: 26.02.17 20:04
Оценка:
Здравствуйте, Privalov, Вы писали:

P>BINARY FLOAT(16) — это как-то мало. ЕМНИП, 53 должно быть.


Тогда мне изменила помять, в том что значит BINARY/DECIMAL в этом описании. Посыпаю голову пеплом.
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re[6]: Круглое число
От: Privalov  
Дата: 26.02.17 20:46
Оценка:
Здравствуйте, pagid, Вы писали:

P>>BINARY FLOAT(16) — это как-то мало. ЕМНИП, 53 должно быть.


P>Тогда мне изменила помять, в том что значит BINARY/DECIMAL в этом описании. Посыпаю голову пеплом.


Честно говоря, я совсем не помню разницу между BINARY и DECIMAL FLOAT. С FIXED все ясно. Если BINARY, то речь идет о двоичном числе. А если DECIMAL, то число хранится в двоично-десятичном упакованном формате, и вычисления на таких числах страшно тормозят. А вот с FLOAT надо литературу поднимать. Но что-то мне подсказывает, что DEC FLOAT (16) и BIN FLOAT(53) — это одно и то же. Но боюсь наврать.
Re[7]: Круглое число
От: pagid Россия  
Дата: 26.02.17 21:03
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Честно говоря, я совсем не помню разницу между BINARY и DECIMAL FLOAT. С FIXED все ясно. Если BINARY, то речь идет о двоичном числе. А если DECIMAL, то число хранится в двоично-десятичном упакованном формате, и вычисления на таких числах страшно тормозят.

Вот это меня и спутало. На первый взгляд и логично ожидать, что и с FLOAT так же.

P> А вот с FLOAT надо литературу поднимать. Но что-то мне подсказывает, что DEC FLOAT (16) и BIN FLOAT(53) — это одно и то же. Но боюсь наврать.

Похоже на то.

Но тогда остается вопрос, как это числа так ловко "округлялись" при преобразовании в двойную точность. Какие-то процедуры стандартной библиотеки языка неявно вызывались? но что-то сомнения меня гложут, и всяко-разно тогда в Фортрановском компиляторе должно было быть сделано так же, что еще большие сомнения вызывает.
Отредактировано 26.02.2017 21:31 pagid . Предыдущая версия .
Re[3]: Круглое число
От: Privalov  
Дата: 26.02.17 21:23
Оценка:
Здравствуйте, netch80, Вы писали:

N>Вот с single были некоторые проблемы за счёт сокращения диапазона порядков до 10^38, но и то вылазили у редчайших клиентов, а остальные были довольны устойчивыми 24 битами мантиссы, вместо 21-24, как в S/360.


Я в курсе. У нас REAL*4 просто нигде не использовалось. Переход прошел практически безболезненно.

P>> Причем все нармально работало и в MS DOS, и с DOS-extender-ом, и в Чикаге, и в Полуоси.


N>А при чём тут ось?


Да в общем, конечно, ни причем. Я просто вспомнил, как в MS DOS нарвался на сегментную память. Пришлось длинным массивам атрибут HUGE навесить. Вычисления, разумеется, шли везде одинаково. FPU присутствовал у нас везде.

N>Вот с fpa библиотекой можно было иногда получать странноватые результаты — но на наших тогдашних XT и AT/286 без FPU это было всё равно хорошо.


FPU, как я уже сказал, у нас были всегда, поэтому эта штука оказалась не нужна. Даже на 286.
Re[7]: Круглое число
От: Michael7 Россия  
Дата: 26.02.17 22:14
Оценка:
Здравствуйте, Privalov, Вы писали:

P>Честно говоря, я совсем не помню разницу между BINARY и DECIMAL FLOAT. С FIXED все ясно. Если BINARY, то речь идет о двоичном числе. А если DECIMAL, то число хранится в двоично-десятичном упакованном формате, и вычисления на таких числах страшно тормозят.


Кстати о тормозах, но ведь у x86-х же есть в железе BCD-формат, но на практике его кажется очень мало кто из компиляторов использовал.
Re[8]: Круглое число
От: pagid Россия  
Дата: 26.02.17 22:19
Оценка:
Здравствуйте, Michael7, Вы писали:

M>Кстати о тормозах, но ведь у x86-х же есть в железе BCD-формат, но на практике его кажется очень мало кто из компиляторов использовал.

Это наследие i8080, а возможно даже и i8008 предназначенного для калькуляторов. В x64 BCD нет
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re[9]: Круглое число
От: Michael7 Россия  
Дата: 27.02.17 00:33
Оценка:
Здравствуйте, pagid, Вы писали:

P>Это наследие i8080, а возможно даже и i8008 предназначенного для калькуляторов. В x64 BCD нет


Я о том, что в описываемой ситуации (когда никакого x64 не было, но был BCD) при миграции с ЕС на ПК этим можно было бы, наверное, воспользоваться. Хотя хз, это не плавучка по-любому была, но все-равно вероятно могло помочь при программной реализации типа.
Re[10]: Круглое число
От: pagid Россия  
Дата: 27.02.17 03:32
Оценка:
Здравствуйте, Michael7, Вы писали:

M>Я о том, что в описываемой ситуации (когда никакого x64 не было, но был BCD) при миграции с ЕС на ПК этим можно было бы, наверное, воспользоваться. Хотя хз, это не плавучка по-любому была, но все-равно вероятно могло помочь при программной реализации типа.

Это работало бы очень медленно. Там очень примитивные BCD команды.
... << RSDN@Home 1.2.0 alpha 5 rev. 1495>>
Re[2]: Круглое число
От: Privalov  
Дата: 27.02.17 06:06
Оценка:
Здравствуйте, netch80, Вы писали:


N>А как именно работал там DECIMAL FLOAT?

N>На старой — через BCD арифметику S/360? А то "честным" float там такого нельзя было сделать (там была двоичная плавучка с другими особенностями, но сильно похожая на современную).

Через BCD работал DECIMAL FIXED. Это я на всю жизнь запомнил. А DECIMAL FLOAT работал, ЕМНИП, как фортрановское REAL. Но все же боюсь наврать.
Re[9]: Круглое число
От: кт  
Дата: 27.02.17 06:10
Оценка:
Здравствуйте, pagid, Вы писали:

M>>Кстати о тормозах, но ведь у x86-х же есть в железе BCD-формат, но на практике его кажется очень мало кто из компиляторов использовал.

P>Это наследие i8080, а возможно даже и i8008 предназначенного для калькуляторов. В x64 BCD нет
Интересно, в какой книге первой было написано, что BCD нужно для калькуляторов и его забыли выкинуть из 8080 после 8008?
BCD нужно для финансово-экономических расчетов и его использовали все компиляторы с Кобола, например.
Финансово-экономические расчеты никуда не делись, а вот новое поколение разработчиков Intel о них, похоже, ничего не знает
Здесь это уже обсуждалось не раз, но опять в памяти остаются только калькуляторы.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.