Bug in collatz crate?

Pretty new to rust and am wondering if the following is a bug or something I am doing wrong:
I am trying to learn rust by doing project euler. I am at problem 14 which includes collatz sequence.I am using the colltaz crate but run into the following:

  println!("{}",collatz::total_stopping_time(837798));
  println!("{}",collatz::total_stopping_time(837800));
  println!("{}",collatz::total_stopping_time(837799));

the last one crashes..
thread 'main' panicked at 'attempt to multiply with overflow', /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ops/arith.rs:369:1

any ideas?

Hard to say without a proper stacktrace, but it could be that the crate is using recursion and the stack overflowed.

Probably the numbers you're calculating are getting too large for your integer type. Are you using u32 or maybe usize? Because u32 won't be big enough. Try u64 instead.

4 Likes

I'll have a look into how to do that

the number of steps should be around 524.. the intermediate numbers might be huge, but I cannot control those, they are processed inside the crate..
Thanks

Yes, the intermediate numbers will reach the 10s of billions.

What crate are you referring to? You should be able to control everything you need to solve the problem (that's the point of an exercise after all).

2 Likes

I'm using collatz = "0.5.0". I have done all those in Freepascal and wrote my own function, but since the crate existed in Rust I decided to use it.. I might write my own function again, it is good practice.

Thanks

Oops, I see now you even said "collatz crate" in the title and I straight overlooked it.

total_stopping_time is generic; it takes any type that implements Copy and num::Integer. When you call it like this:

  println!("{}",collatz::total_stopping_time(837799));

The compiler has to eventually figure out the type of your literal (u32, i128, ...). Before it figures that out, it just flags the literal as "some kind of (built-in) {integer}". In this case, all of the built-in integer types meet the bounds of total_stopping_time. In situations like these, Rust falls back to a default integer type: i32. (The default float type is f64.)

So that's what's going on -- you're using i32s and they're overflowing on the intermediate values.

And thus the actual solution to your OP is to be explicit about your literal types:

println!("{}", collatz::total_stopping_time(837799_u64));

Playground. Sorry for not understanding your actual question initially.


(Incidentally, this crate seems fine, but anyone can publish a crate -- so you can't really tell if one is any good (or familiar to everyone) just because it's on crates.io.)

5 Likes

No. The error message explicitly says that it's a numerical (multiplication) overfow, it is not a stack overflow.

1 Like

Awesome
Thanks for your help. I need to define the variable not just for the value I give to the function, but also for the value it might get inside the function..

Marking the argument as u64 is just to aid type deduction; there is no “variable” defined here. You could also explicitly provide the type parameter and use

collatz::total_stopping_time::<u64>(837799)

although it’s more verbose and less idiomatic.

Thanks, I got it to work.. then wrote my own function..