После нескольких лет перерыва в программировании я пытаюсь снова набрать скорость, изучая Perl 6. Эта серия статей задумана как своего рода отчет о прогрессе, демонстрирующий не только то, что я узнал, но и все мои недоразумения и ошибки.

Когда я проверил свой почтовый ящик сегодня утром, я получил обычное письмо от Medium с рекомендациями, которые я должен прочитать. Это вызвало *) мой интерес: COBOL держит вас в заложниках с Math?

Это увлекательное чтение о том, как финансовые и правительственные учреждения, а также авиакомпании и многие другие до сих пор используют программное обеспечение, написанное на Cobol. Марианна Беллотти, автор, объясняет, почему они все еще используют его и почему Cobol в некоторых случаях все еще может быть лучше, чем, например, Java.

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

168.939167671  | 4.9990600687785413938424188

В первом случае в Python используются числа с плавающей запятой по умолчанию, во втором - результат использования типа Decimal с фиксированной точкой из пакета decimal. Последнее ближе к правильному, чем первое. И, как видите: разница не маргинальна, а огромна; представьте, во что обошлись бы такие ошибки округления IRS или вашему местному банку, если бы они были приняты за чистую монету.

Поддержка Cobol плавающих значений с фиксированной запятой является причиной того, почему эти учреждения все еще полагаются на Cobol, а не на новые технологии, такие как Java (которая обрабатывает числа с плавающей запятой так же, как в Python по умолчанию).

И вот одно из реальных отличий Perl 6 от других языков. Я видел, как Ларри Уолл где-то сказал, что для Perl 6 ему нужен язык, на котором работает. И секрет в том, что тип данных Rat (рациональный). Крысы представляют числа как дроби, поэтому большая часть ошибок, связанных с точностью, здесь не отображается.

Что еще лучше: не нужно об этом думать.

Ниже представлена ​​реализация кода Python на Perl 6. Сравните версию Perl 6 с кодом Python в статье COBOL держит вас в заложниках с математикой? (на самом деле нет, теперь вы должны прочитать это, прежде чем читать дальше. Большая часть того, что будет дальше, будет иметь меньший смысл, если вы этого не сделали).

#!/usr/bin/env perl6
sub rec($y, $z) {
    return 108 - ((815-1500/$z)/$y);
}
sub default-behavior(Int $N, $default) {
    my @x = (4, 4.25);
    for (2..$N+1) -> $i {
        my $n = rec(@x[$i-1], @x[$i-2]);
        $n = $n.Num if !$default;
        @x.append($n);
    }
    return @x;
}
my @y = default-behavior(20, True);
my @n = default-behavior(20, False);
for @y.kv -> $i, $p {
    my ($a, $b) = $p.Rat.nude;
    say $i.fmt("%02d") ~ " | " ~ @y[$i].fmt("%3.10f") ~ 
        " | "~ @n[$i].fmt("%3.10f") ~ " | $a/$b";
}

Рассмотрим вывод ниже и сравните его с выводом Python. Вывод кода Perl 6 немного отличается: первый столбец не требует пояснений, второй показывает поведение Perl6 по умолчанию, третий показывает представление с плавающей запятой - ошибки, которые я должен явно принудить, - а четвертый показывает внутреннюю дробь. представление числа во втором столбце.

00 | 4.0000000000 | 4.0000000000 | 4/1
01 | 4.2500000000 | 4.2500000000 | 17/4
02 | 4.4705882353 | 4.4705882353 | 76/17
03 | 4.6447368421 | 4.6447368421 | 353/76
04 | 4.7705382436 | 4.7705382436 | 1684/353
05 | 4.8557007126 | 4.8557007126 | 8177/1684
06 | 4.9108474991 | 4.9108474991 | 40156/8177
07 | 4.9455374041 | 4.9455374035 | 198593/40156
08 | 4.9669625818 | 4.9669625693 | 986404/198593
09 | 4.9800457014 | 4.9800454510 | 4912337/986404
10 | 4.9879794485 | 4.9879744208 | 24502636/4912337
11 | 4.9927702881 | 4.9926694965 | 122336033/24502636
12 | 4.9956558915 | 4.9936371620 | 611148724/122336033
13 | 4.9973912684 | 4.9569659720 | 3054149297/611148724
14 | 4.9984339439 | 4.1829179009 | 15265963516/3054149297
15 | 4.9990600720 | -14.4971549507 | 76315468673/15265963516
16 | 4.9994359371 | 139.4819461498 | 381534296644/76315468673
17 | 4.9996615241 | 101.4151436597 | 1907542343057/381534296644
18 | 4.9997969007 | 100.0697650170 | 9537324294796/1907542343057
19 | 4.9998781355 | 100.0034856744 | 47685459212513/9537324294796
20 | 4.9999268795 | 100.0001742733 | 238423809278164/47685459212513

Это длинный текст, чтобы прояснить очень простой момент: ошибки математики и округления, показанные в статье COBOL держит вас в заложниках с помощью математики? не является проблемой для Perl6, поскольку тип данных Rat гарантирует, что этого не произойдет.

Что еще лучше: правильное поведение - это значение по умолчанию в Perl6. На самом деле я должен прямо попросить о проблеме - преобразовав Rat в Num, как показано здесь:

$n = $n.Num if !$default; 

Короче говоря, Perl6 мягко держит вас за руку и просто предполагает, что вы хотите правильного поведения, вместо того, чтобы заставлять вас работать над неправильным поведением.

Теперь - я не думаю, что финансовые учреждения откажутся от Cobol для Perl6 только из-за этого. Но по крайней мере другие языки должны быть вдохновлены этим и, возможно, реализовать аналогичные вещи в будущих версиях. Так же, как perlre в конечном итоге нашел свое отражение во многих других языках.

Замечание: я должен сказать, что мне было трудно определить функцию-убийцу Perl6 - двадцать лет назад Perl5 использовал сложную обработку регулярных выражений в качестве своей функции-убийцы. Но я должен сказать, что, может быть, что-то из этого может быть? Статистика и математика машинного обучения и искусственного интеллекта в наши дни в моде. Они зависят от правильной математики.

Что бы произошло, если бы мы расширили правильную математику и внедрили ML / AI как первоклассный гражданин Perl6, значительно упростим его по сравнению с существующими решениями - спрячем мельчайшие детали - и сделаем Perl6 AI инструмент для новичков? Тогда мы говорим об убийственной функции!

А пока: веселитесь с Крысами. Они похожи на своих собратьев-грызунов - они повсюду и потрясающие, когда вы их понимаете.

PS! Думаю, я снова наделал много ошибок и даже кое-что не понял. Не стесняйтесь снова писать мне комментарии и исправления. Я люблю узнавать больше и забывать о своих заблуждениях.

*) Спасибо Дэйву Кроссу за то, что он указал на то, что в английском что-то вызывает мой интерес, а не пиков . Удивительно, как в английском много похожих по звучанию слов, которые пишутся по-разному, а иногда даже на удивление по-разному.