Raku: Attempt to divide by zero when coercing Rational to Str

Viewed 107

I am crunching large amounts of data without a hitch until I added more data. The results are written to file as strings, but I received this error message and I am unable to find programming error after combing my codes for 2 days; my codes have been working fine before new data were added.

Died with the exception:
    Attempt to divide by zero when coercing Rational to Str
      in sub analyzeData at /home/xyz/numberCrunch.p6 line 2720
      in block  at /home/xyz/numberCrunch.p6 line 3363

Segmentation fault (core dumped)

The line 2720 is the line that outputs to file: $fh.say("$result");

So, Rational appears to be a delayed evaluation. Is there a way to force immediate conversion of Rational to decimals? Or make Rational smarter by enabling it to detect 0 denominators early?

2 Answers

First of all: a Rat with a denominator of 0 is a perfectly legal Rational value. So creating a Rat with a 0 denominator will not throw an exception on creation.

I see two issues really:

  • how do you represent a Rat with a denominator of 0 as a string?
  • how do you want your program to react to such a Rat?

When you represent a Rats as a string, there is a good chance you will lose precision:

say 1/3;  # 0.333333

So the problem with Rat to string conversion is more general. Fortunately, there's the .raku method that will not throw:

say (1/3).raku;   # <1/3>
say (42/0).raku;  # <42/0>

Now, if you want your program to just not print the value to the file handle if the denominator is 0, then you have several options:

  • prefix with try
try $fh.say($result)
  • check for 0 denominator explicitly
$fh.say($result) if $result.denominator

Finally, the final error message: "Segmentation fault (core dumped)" is a bit worrying. If this is not a multi-threaded program, we should probably try to find out why that is happening: an execution error should not create a segfault. If it is, then maybe we need to look at your code closer to find out if there are any race conditions on structures such as arrays and hashes.

There is a perfectly logical reason that 1/0 doesn't immediately throw.

Let's say you have a floating point number that you want to coerce into a Rat, and back again.

my Num() $a = Inf;
my Rat() $b = $a;
my Num() $c = $b;

say $c;

What do you expect the say $c statement to print?

Inf

What would happen if you wrote say $b?

say $b;
Attempt to divide by zero when coercing Rational to Str

What are the contents of $b?

say $b.nude.join('/');
1/0

Now what if you do a division and immediately coerce it to a Num?

say ( 1/0).Num;
say ( 0/0).Num;
say (-1/0).Num;
Inf
NaN
-Inf
Related