-
Notifications
You must be signed in to change notification settings - Fork 33
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
Make Display for Decimal more human-friendly #477
Conversation
d8b9b26
to
97f63ac
Compare
src/types/decimal.rs
Outdated
// The index of the decimal | ||
let i_d = len as i64 + self.exponent; |
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.
What does "index of the decimal" mean?
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 added a comment:
// The index of the decimal, relative to the magnitude representation
// 0123
// Given ABCDd-2, the decimal gets inserted at position 2.
let i_d = len as i64 + self.exponent;
src/types/decimal.rs
Outdated
write!(f, "{}.{}d{}", &digits[0..1], &digits[1..len], (i_d - 1)) | ||
} else if self.exponent > 0 { | ||
// e.g. ABC0000. or ABC. | ||
let zeroes = "0".repeat(self.exponent 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.
This line is adding more digits of precision to the output.
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.
Good callout. I've fixed it and the tests pass now.
97f63ac
to
1661c9d
Compare
1661c9d
to
e4c3d5d
Compare
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #477 +/- ##
==========================================
+ Coverage 90.13% 90.16% +0.03%
==========================================
Files 76 76
Lines 13548 13568 +20
==========================================
+ Hits 12211 12234 +23
+ Misses 1337 1334 -3
... and 4 files with indirect coverage changes Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report in Codecov by Sentry. |
src/types/decimal.rs
Outdated
write!(f, "{}.{}", &digits[0..ui_d], &digits[ui_d..len]) | ||
} else if i_d > -6 { | ||
// e.g. 0.ABC or 0.000ABC | ||
let zeroes = "0".repeat(i_d.abs() 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.
Can you please add Clippy's suggestions 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.
I ran into rust-lang/rust-clippy#7416 and had a very frustrating time before I managed to get clippy running.
Fixed the cast_abs_to_unsigned issue.
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.
Later obviated by Zack's format string suggestion.
src/types/decimal.rs
Outdated
// The index of the decimal, relative to the magnitude representation | ||
// 0123 | ||
// Given ABCDd-2, the decimal gets inserted at position 2. | ||
let i_d = len as i64 + self.exponent; |
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.
How about d_index
?
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.
Originally I used decimal_index
, but then rustfmt
forces some of the write!
cases into multiple lines. I shortened some variable names to keep everything on one line because I found the multiline version so much less appealing.
d_index
is similarly too long. I wish I could get rustfmt
to tell me which constraint it's running into, because it seems to not fire when line length is 83 but does fire on line length 84? So maybe it's not line length, maybe it's length of parameter list? I don't know.
src/types/decimal.rs
Outdated
write!(f, "-").unwrap(); | ||
}; | ||
|
||
if self.exponent == 0 && len > 6 { |
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.
Could you make 6
a named constant and/or add a comment explaining how you chose it?
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.
Will do both. Happy to change to some other value, as well.
src/types/decimal.rs
Outdated
// exponent < 0, there is a fractional component | ||
if i_d > 0 { | ||
// e.g. A.BC or AB.C | ||
let ui_d = i_d 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.
If it's helpful, you can shadow the existing name in this scope so you don't have to think of a new one. (IMO, ui_d
is a bit cryptic, though I gather it stands for unsigned_index_of_d
?). Shadowing has the potential to be a bit confusing for readers outside of an IDE, but in this case it only lasts one line.
src/types/decimal.rs
Outdated
write!(f, "{}.{}", &digits[0..ui_d], &digits[ui_d..len]) | ||
} else if i_d > -6 { | ||
// e.g. 0.ABC or 0.000ABC | ||
let zeroes = "0".repeat(i_d.abs() 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.
This will allocate a new string, but you can achieve the same thing using the format string you pass to write!
. See the docs for Fill/Alignment and Sign/#/0 for details.
Alternatively, create one very long static ZEROS: &str = "0000000...";
and just take a slice of the desired length 😛
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.
Using the format string passed to write!
was a great suggestion, took a little fiddling but I like it :D
Co-authored-by: Matthew Pope <81593196+popematt@users.noreply.github.com>
Co-authored-by: Zack Slayton <zack.slayton@gmail.com>
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.
🚀 A nice improvement!
src/types/decimal.rs
Outdated
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
// Inspired by the formatting conventions of Java's BigDecimal.toString() | ||
const WIDE_NUMBER: i64 = 6; // if you think about it, six is a lot 🙃 |
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.
This could be a usize
, which would allow you to skip:
- casting
len as i64
down on line 308 - casting
WIDE_NUMBER as usize
on line 314
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.
Yeah WIDE_NUMBER
should be a usize
.
- If I don't cast
len as i64
on line 308 thendot_index
gets inferred asusize
, but that's not right becausedot_index
should be able to be negative. - As far as I understand it, I either have to cast
WIDE_NUMBER as usize
on line 314 to agree withlen
or castWIDE_NUMBER as i64
on line 324 for easiest comparison with the negative-valueddot_index
there. The latter is the right call becauseWIDE_NUMBER
should be ausize
.
Unless I'm missing something, which is probable :) I'd also happily take feedback or second opinions on the WIDE_NUMBER
concept- whether we ought to have it at all, whether it ought to be applied "evenly" on both whole and fractional numbers, and how large it should be.
Description of changes:
Before this all Decimals would be displayed as e.g. 37d-2 instead of 0.37. After this decimals are displayed as
ABC.DEF
,ABCd3
or0.000ABC
unless the number of padding zeroes grows large, in which case it will fall back toA.BCd-E
for some exponent.This also prefers to quantify the scale of larger numbers, e.g.
ABCDEFGd0
will be written as A.BCDEFGd6 instead ofABCDEFG.
"large" is henceforth "six" until someone changes it ;)
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.