Raku 中的有理数
Rational numbers in Raku
我正在使用 Raku 进行一些计算,因为它有很好的数字类型。但是,我在使用 '.raku'
时遇到问题
say (1/6+1/6).raku
#<1/3>
我们得到这个。然而,
say (1/10+1/10).raku
#0.2
这是一个错误吗?我预计 <1/5>。会发生什么?
在 Raku 中,0.2
构造一个 Rat
,因此产生的结果与编写 1/5
(将常量折叠)或 <1/5>
(字面形式)。只有在指定指数的情况下才能得到浮点数(例如 2e-1
)。
.raku
(以前称为 .perl
)方法的工作是生成一些东西,如果 EVAL
会往返并产生相同的值。在 1/5
的情况下,它可以精确地表示为小数,因此它会产生 0.2
。它仅在小数形式不能往返时才采用小数表示法。
您始终可以使用 .numerator
和 .denominator
方法恢复分子和分母,并根据需要格式化。另外 .nude
方法 returns 分子和分母的列表,如果需要可以用 /
加入:
say (1/6+1/6).nude.join("/"); # 1/3
say (1/10+1/10).nude.join("/"); # 1/5
你好@milou123 我也有点惊讶 raku 恢复为十进制表示法 - 我可以看到某些上下文 - 例如教小数算术将受益于 "keep as rat" 模式。话虽如此,最终只有一种方法可以 .raku 某些东西并且十进制是默认表示是有道理的。
当然,有了raku,你也可以稍微改变一下语言。在这种情况下,我发明了一个新的“→”后缀运算符...
multi postfix:<→> ( Rat:D $r ) { $r.nude.join("/") }
say (1/5+1/5)→; # 2/5
如果内置的 'raku' 方法可以用类似的方式重写,我还不够聪明,我很想知道如何简洁地做到这一点的建议...
在 Julia 中试试这个:
julia> 1 // 10 + 1 // 10
1//5
julia> typeof(1 // 10 + 1 // 10)
Rational{Int64}
julia> 1 // 2 + 1 // 3
5//6
julia> typeof(1 // 2 + 1 // 3)
Rational{Int64}
在Rat.pm6实现中,我们只能调用Rat类型的.raku
方法来得到预期的格式:
multi method raku(Rat:D: --> Str:D) {
if $!denominator == 1 {
$!numerator ~ '.0'
}
else {
my $d = $!denominator;
unless $d == 0 {
$d = $d div 5 while $d %% 5;
$d = $d div 2 while $d %% 2;
}
if $d == 1 and (my $b := self.base(10,*)).Numeric === self {
$b;
}
else {
'<' ~ $!numerator ~ '/' ~ $!denominator ~ '>'
}
}
}
我正在使用 Raku 进行一些计算,因为它有很好的数字类型。但是,我在使用 '.raku'
时遇到问题say (1/6+1/6).raku
#<1/3>
我们得到这个。然而,
say (1/10+1/10).raku
#0.2
这是一个错误吗?我预计 <1/5>。会发生什么?
在 Raku 中,0.2
构造一个 Rat
,因此产生的结果与编写 1/5
(将常量折叠)或 <1/5>
(字面形式)。只有在指定指数的情况下才能得到浮点数(例如 2e-1
)。
.raku
(以前称为 .perl
)方法的工作是生成一些东西,如果 EVAL
会往返并产生相同的值。在 1/5
的情况下,它可以精确地表示为小数,因此它会产生 0.2
。它仅在小数形式不能往返时才采用小数表示法。
您始终可以使用 .numerator
和 .denominator
方法恢复分子和分母,并根据需要格式化。另外 .nude
方法 returns 分子和分母的列表,如果需要可以用 /
加入:
say (1/6+1/6).nude.join("/"); # 1/3
say (1/10+1/10).nude.join("/"); # 1/5
你好@milou123 我也有点惊讶 raku 恢复为十进制表示法 - 我可以看到某些上下文 - 例如教小数算术将受益于 "keep as rat" 模式。话虽如此,最终只有一种方法可以 .raku 某些东西并且十进制是默认表示是有道理的。
当然,有了raku,你也可以稍微改变一下语言。在这种情况下,我发明了一个新的“→”后缀运算符...
multi postfix:<→> ( Rat:D $r ) { $r.nude.join("/") }
say (1/5+1/5)→; # 2/5
如果内置的 'raku' 方法可以用类似的方式重写,我还不够聪明,我很想知道如何简洁地做到这一点的建议...
在 Julia 中试试这个:
julia> 1 // 10 + 1 // 10
1//5
julia> typeof(1 // 10 + 1 // 10)
Rational{Int64}
julia> 1 // 2 + 1 // 3
5//6
julia> typeof(1 // 2 + 1 // 3)
Rational{Int64}
在Rat.pm6实现中,我们只能调用Rat类型的.raku
方法来得到预期的格式:
multi method raku(Rat:D: --> Str:D) {
if $!denominator == 1 {
$!numerator ~ '.0'
}
else {
my $d = $!denominator;
unless $d == 0 {
$d = $d div 5 while $d %% 5;
$d = $d div 2 while $d %% 2;
}
if $d == 1 and (my $b := self.base(10,*)).Numeric === self {
$b;
}
else {
'<' ~ $!numerator ~ '/' ~ $!denominator ~ '>'
}
}
}