bigdecimal-rs icon indicating copy to clipboard operation
bigdecimal-rs copied to clipboard

Add `From` impls for primitives

Open sgrif opened this issue 8 years ago • 6 comments

There's currently no way to construct a BigDecimal instance in a way that cannot fail. This is a huge hit to ergonomics. There should be a From impl for all of the numeric types (both integral and floating point)

sgrif avatar May 11 '17 21:05 sgrif

Good point! num_traits::FromPrimitive was imported, but never implemented. Huge oversight, thanks.

The simplest implementation of from_f32/f64 would be to print to string and then build a decimal from that string; not very efficient but it would be correct for now, then get more efficient after the internals of BigDecimal get more efficient.

The standard library almost had an integer decode method for floating point numbers, which would have been perfect for this usecase, but it's been deprecated.

Note that interpreting decimals from floating point values will return "strange" results, but I think this is to be expected.

python example:

>>> Decimal(12.34)
Decimal('12.339999999999999857891452847979962825775146484375')

rust BigDecimal test:

  assert_eq!(BigDecimal::from_str("12.3399999999999999").unwrap(),
             BigDecimal::from_f32(12.34).unwrap());

akubera avatar May 12 '17 15:05 akubera

Alright, FromPrimitive is implemented in e46b64af57bd1d54668de6e7f72d79871710b05d

Of course, you meant From<u32>, From<f64>, etc... like every other rust struct, not the num traits. I will get on that next.

akubera avatar May 12 '17 15:05 akubera

Alright, From<u...,i...,f...> are implemented, and instead of going to some arbitrary precision, I'm using the std::f32::DIGITS (== 6) & std::f64::DIGITS ( == 15) constants to indicate precision, so 12.34f32 is equivalent to "12.34000" and 12.34f64 is "12.34000000000000".

The alternative would be to use the decimal's context object (not-yet-implemented) to generate the precision (which must be what python does). I can't think of a reason why you would want to introduce such floating-point errors into numbers, but if anyone.

I will leave this issue open for comments until I publish the updates sometime tonight (EDT).

Further discussion is encouraged on the project's gitter page

akubera avatar May 12 '17 18:05 akubera

I gave this a try, and it looks like the From<f32> and From<f64> impls are incredibly slow. It seems like it's doing string allocation? Seems like it should probably not be doing that.

sgrif avatar May 13 '17 10:05 sgrif

I was trying to avoid a heap allocation by "printing" to a stack-allocated array like this: https://is.gd/vu1smV, but while it works on playrust, when I run it locally it always crashes, so that's unfortunate.

To avoid the string stuff I'll have to implement some bit manipulation, but that will take some time to ensure it's right.

akubera avatar May 14 '17 01:05 akubera

Alright, I pushed a new implementation of From and From to the branch feature/from-primitive. @sgrif, please build against that and check if the speed is acceptable (also if you could check for correctness that'd be helpful, too).

As far as I can tell, really small numbers might lose some accuracy, but people using such numbers in floating point representation are already in trouble.

akubera avatar May 17 '17 20:05 akubera

This was merged in 7247fb2. Closing the issue, now.

akubera avatar Apr 01 '24 04:04 akubera