Поэлементное сравнение с определенной точностью

Я ищу тестовый вывод моей функции (которая возвращает массив) с ожидаемым выходным массивом.

Пример:

use Test;
sub myoutput($n) {
    (1..$n)>>.sqrt
}

is myoutput(3), (1, 1.4142135623730951, 1.7320508075688772);

Выглядит нормально, но я хочу установить точность 1e-12.

У меня получилось следующее:

sub element_wise_testing_with_precision(@functionoutput, @expectedoutput, $precision) {
    die "Provide equal elements!" if +@functionoutput != +@expectedoutput;
    loop (my $i = 0; $i < +@functionoutput; $i++)  {
        is-approx @functionoutput[$i], @expectedoutput[$i], $precision;
    }
}


my @expected = (1, 1.4142135623730951, 1.7320508075688772);
element_wise_testing_with_precision(myoutput(3), @expected, 1e-12)

Работает (!), но не уверен, что это правильно. Существуют ли способы сделать это с помощью оператора Z или Гипероператора, поскольку они, похоже, выполняют поэлементные операции?

Абсолютная точность или относительная точность?

jubilatious1 06.10.2023 08:20

Это :$abs-tol, абсолютная точность.

Suman 06.10.2023 13:58
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
2
256
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ваши представления о Hyper и zip/операторе Z совершенно верны: с любым из них можно делать все, что хочешь. Недостающий кусочек головоломки — это каррирование , которое Раку делает с помощью &предполагая (или с помощью Что угодно каррирования, но это здесь неприменимо). Мы можем использовать &assuming, чтобы указать точность в качестве третьего аргумента, например: &is-approx.assuming(*, *, $precision). Или, поскольку &is-approx позволяет указать точность с помощью именованного аргумента, мы можем упростить это до &is-approx.assuming: :abs-tol($precision).

Как только мы это сделаем, мы можем применить наш новый элемент функции с помощью метаоператоров Hyper или Z. Обратите внимание: поскольку метаоператоры ожидают инфиксный оператор, нам нужно будет использовать инфиксную форму нашей функции, заключая нашу функцию в квадратные скобки.

Вот ваш код с этими минимальными изменениями:

sub element_wise_testing_with_precision(@functionoutput, @expectedoutput, $precision) {
    die "Provide equal elements!" if +@functionoutput != +@expectedoutput;

    my &close-enough = &is-approx.assuming(*,*, $precision);
    @functionoutput «[&close-enough]» @expectedoutput

  # or this also works:
  # @functionoutput Z[&close-enough] @expectedoutput
}

Вот версия с некоторыми изменениями, чтобы сделать ее более идиоматичной:

sub element-wise-is-approx(@got, @expected, $abs-tol) {
    PRE { +@got == +@expected }

    my &close-enough = &is-approx.assuming: :$abs-tol;
    @got «[&close-enough]» @expected
}

element-wise-is-approx(myoutput(3), @expected, 1e-12);

Действительно, мы могли бы сделать это даже в строке, как показано ниже. Здесь мы переключаемся на версию Hyper (» «), не поддерживающую DWIM, чтобы обеспечить использование аргументов одинакового размера.

myoutput(3) »[&(&is-approx.assuming(*,*,1e-12))]« @expected

(Обратите внимание, что дополнительный &( ) в инфиксном операторе необходим для разъяснения наших намерений компилятору Raku.)

Как всегда отличное объяснение. Много нового для меня. Спасибо @codesections Несколько комментариев: во второй функции @got «[&is-approx]» @expected может быть опечатка, думаю, &close-enough должно быть посередине. В вашем третьем коде я получаю это предупреждение Potential difficulties: Useless use of »[&(&is-approx.assuming(*,*,1e-12))]« in sink context. Есть идеи, как от этого избавиться?

Suman 30.09.2023 17:51

@SumanKhanal, спасибо за указание на (теперь исправленную) опечатку и предупреждение о «контексте приемника». Я считаю, что последнее — ошибка Ракудо; Я сообщу о проблеме, если ее еще нет. Пока это не исправлено, вы можете отключить предупреждение, присвоив результат неиспользуемой переменной my $ = myoutput(3) »[&(&is-approx.assuming(*,*,1e-12))]« @expected или запустив ее в subtest. Или отключить все предупреждения с помощью блока quietly (docs.raku.org/syntax/quietly%20%28statement%20prefix%29), но здесь это кажется излишним.

codesections 30.09.2023 21:17

Ошибка уже была: github.com/rakudo/rakudo/issues/4424 Я добавил некоторые подробности и дал ссылку на этот вопрос SO.

codesections 30.09.2023 21:31

Это кажется чрезвычайно продвинутым ответом, особенно для новых пользователей Raku. Есть ли шанс, что ОП сочтет $*TOLERANCE из 1e-15 приемлемым? См. второй ответ на этот вопрос (при желании добавьте .grep).

jubilatious1 02.10.2023 21:49

Мне неясно, хочет ли ФП абсолютной или относительной терпимости. Может ли @SumanKhanal внести ясность?

jubilatious1 06.10.2023 12:55

@jubilatious1 Это :$abs-tol, абсолютная точность.

Suman 06.10.2023 15:37

Попробуйте встроенный в Raku оператор =~= «толерантности» с вызовами Hyper/Z, которые вы себе представляете.

Оператор «допуска» =~= считывает динамическую переменную $*TOLERANCE, которая по умолчанию равна 1e-15, см. ссылку внизу.

~$ seq 1 16 |  \
   awk '{print sqrt($0)}' |  \
   raku -e  'my @awk = lines;  
             my @raku = (1..16).map: *.sqrt;  \
             .say for [Z=~=] @awk,@raku;'
True
False
False
True
False
False
False
False
True
False
False
False
False
False
False
True

Выделение входных данных, первый awk:

~$ seq 1 16 | awk '{print sqrt($0)}'
1
1.41421
1.73205
2
2.23607
2.44949
2.64575
2.82843
3
3.16228
3.31662
3.4641
3.60555
3.74166
3.87298
4

И точность Раку по умолчанию:

~$ raku -e '.sqrt.put for (1..16);'
1
1.4142135623730951
1.7320508075688772
2
2.23606797749979
2.449489742783178
2.6457513110645907
2.8284271247461903
3
3.1622776601683795
3.3166247903554
3.4641016151377544
3.605551275463989
3.7416573867739413
3.872983346207417
4

Я понимаю, что ФП запросил допуск 1e-12, но, может быть, более высокий допуск 1e-15 может оказаться приемлемым? Не видя желаемого результата ОП, я могу только догадываться, что однострочник [Z=~=] может быть приемлемым, с дополнительным вызовом .grep или без него.

[ Re: Допуск — я не вижу способа установить динамическую переменную $*TOLERANCE так, чтобы инфиксный оператор =~= считывал новое значение. Установка $*TOLERANCE = 1e-12 выдает ошибку. Невозможно изменить неизменяемый Num (1e-15)].

[Раку также имеет похожую функцию, is-approx].

https://docs.raku.org/routine/%3D~%3D
https://docs.raku.org/routine/is-approx
https://unix.stackexchange.com/a/742940/227738

my $*TOLERANCE = ... сделал бы новую лексическую динамическую переменную для =~=, чтобы ее можно было видеть, не затрагивая глобальную, живущую в ПРОЦЕССЕ, которая привязана к 1e-15, настолько неизменной, как вы сказали, что, я думаю, хорошо, чтобы не менять глобально толерантность повсюду. И что еще более важно, это проверяет относительную разницу, а не абсолютную, которую задавший вопрос достигает с помощью параметра abs-tol is-approx.
Mustafa Aydın 04.10.2023 12:54

Другие вопросы по теме