-
Notifications
You must be signed in to change notification settings - Fork 160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add pad and padded to FixedDecimal #1195
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, this is about right, but let's sync on the details
utils/fixed_decimal/src/decimal.rs
Outdated
/// dec.pad(2); | ||
/// assert_eq!("042", dec.to_string()); | ||
/// | ||
/// dec.pad(-2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this be additive with multiply_pow10()
? E.g. suppose I had:
let mut dec = FixedDecimal::from(1234);
dec.multiply_pow10(-1); // "123.4"
dec.pad(-2); // "123.400" ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should be normalizing before we pad, i.e. convert everything into (n digits) + n magnitude.
We should definitely add doctests for the behavior here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or, well, if minus padding, we first put it in a form where it is not already padded on the right, and if plus-padding, put it in a form where it's not already padded on the left
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually wait I think the data model doesn't need this 😄
utils/fixed_decimal/src/decimal.rs
Outdated
let cut = self.magnitude - self.upper_magnitude; | ||
|
||
self.magnitude = self.upper_magnitude; | ||
self.digits.drain(0..(cut as usize)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Please add a test case that triggers the case where cut
is larger than self.digits.len()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
utils/fixed_decimal/src/decimal.rs
Outdated
Ordering::Greater => self.upper_magnitude = magnitude, | ||
_ => (), | ||
pub fn pad_or_trunc_left(&mut self, shift: i16) { | ||
self.upper_magnitude = match self.upper_magnitude + shift >= 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Please use checked_add
instead of +
. You may need to make the function return Result
; see multiply_pow10
. Add a test case for this behavior at the bottom of the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
utils/fixed_decimal/src/decimal.rs
Outdated
Ordering::Less => self.lower_magnitude = magnitude, | ||
Ordering::Greater => self.upper_magnitude = magnitude, | ||
_ => (), | ||
pub fn pad_or_trunc_left(&mut self, shift: i16) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub fn pad_or_trunc_left(&mut self, shift: i16) { | |
pub fn pad_or_truncate_left(&mut self, shift: i16) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
utils/fixed_decimal/src/decimal.rs
Outdated
/// ``` | ||
pub fn padded(mut self, magnitude: i16) -> Self { | ||
self.pad(magnitude); | ||
pub fn padded_or_trunced_left(mut self, magnitude: i16) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub fn padded_or_trunced_left(mut self, magnitude: i16) -> Self { | |
pub fn padded_or_truncated_left(mut self, magnitude: i16) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
utils/fixed_decimal/src/decimal.rs
Outdated
/// assert_eq!("000", dec.to_string()); | ||
/// | ||
/// dec.pad_or_truncate_left(-1000); | ||
/// assert_eq!("", dec.to_string()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issue: don't put the FixedDecimal in a state where it returns empty strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so, what should we do if the user is deleting all the numbers? shall we consider returning an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, we should leave a 0 in the ones place and never remove it.
0042.10 --> 042.10 --> 42.10 --> 2.10 --> 0.10
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could consider allowing the removal of the zero digit, but I'd like that to be a separate PR, because right now FixedDecimal is defined in such a way that we always guarantee at least one digit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, done
utils/fixed_decimal/src/decimal.rs
Outdated
/// dec.pad_or_truncate_left(-1); | ||
/// assert_eq!("2", dec.to_string()); | ||
/// | ||
/// let mut dec = FixedDecimal::from(1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: The exhaustive behavior tests should go in a unit test at the bottom of the file. Only use docs tests for the main illustrative tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this looks good, but it occurs to me that the user may need non-padding truncation as well (WearOS does)
I think we need functions that provide both:
- the ability to say "make this have exactly X digits before/after the decimal point"
- the ability to say "make this have at most X digits after the decimal point"
- the ability to say "make this have at least X digits before the decimal point"
I don't think truncating on the LHS is that useful, and I think padding on the RHS is somewhat useful but you need a way to opt out.
I wonder if the API should be:
pad_left()
truncate_right()
pad_or_truncate_right()
We could also get by with pad()
, truncate()
, and pad_or_truncate()
all accepting negative integers though I don't see much of a use case for each one so I'd prefer having them, by default, working on the direction this is more useful for. @sffc thoughts?
@Manishearth #1176 has my thoughts on the current proposed algorithm. The API that @younies proposed already allows for either either left* padding (positive argument) or left truncation (negative argument). Right* padding and right truncation should be handled by #1177. A use case for left truncation is removing the century from year values, like in short date formatting ("today's date is 11/29/21"). * I say "left" and "right" even though certain scripts like Adlam write their digits in the opposite direction. I'm happy to bikeshed the name of these functions. |
Fixes #1176