- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
seq: use augmenting addition to update value #2615
Conversation
Very interesting! This does indeed mitigate the issue, but it's not quite solved yet. I just tried:
and GNU includes I checked out the FreeBSD implementation and they use the multiplication method with an additional check for the last value: /*
* Did we miss the last value of the range in the loop above?
*
* We might have, so check if the printable version of the last
* computed value ('cur') and desired 'last' value are equal. If they
* are equal after formatting truncation, but 'cur' and
* 'last_shown_value' are not equal, it means the exit condition of the
* loop held true due to a rounding error and we still need to print
* 'last'.
*/
asprintf(&cur_print, fmt, cur);
asprintf(&last_print, fmt, last);
if (strcmp(cur_print, last_print) == 0 && cur != last_shown_value) {
fputs(last_print, stdout);
fputs(sep, stdout);
} I would imagine that using the multiplication method would also minimize drifting of the values, although I'm not sure how big of a problem that is. |
AFAIK gnu uses |
So maybe the FreeBSD approach can offer a bit more protection, but we may not be completely safe against this type of incompatibility. |
Arbitrary-precision decimal arithmetic might be ideal for correctness, because all the input is decimal to begin with. Maybe with this crate. That would make it trickier to support the |
I have updated this pull request to use the |
66c0fee
to
b79e93b
Compare
I just updated this pull request with support for the NaN error message, but @blyxxyz pointed out that there are some further use cases (namely, |
Pull request #2647 adds two missing unit test cases that witness our support of |
Change from using `print!()` to using `stdout.write_all()` in order to allow the main function to handle broken pipe errors gracefully.
Create the new `number.rs` module to contain the `Number` enumeration and the trait implementation for parsing a `Number` from a string.
Fix a floating-point precision issue with the update in the main loop of `seq`. Before this commit, the behavior was $ seq 0.1 -0.1 -0.2 0.1 0.0 -0.1 which was incorrect: -0.2 should be printed as well. This was happening because the update in the main loop was essentially value = start + (i * increment); which caused `value` to become `-0.20000000000000004`. That exceeds the lower bound of -0.2, so that number was not printed. By using the `bigdecimal` crate to represent floats of (practically) arbitrary precision, we eliminate the issue.
Hmm... I'm not sure how to do this without having a |
b79e93b
to
02366e6
Compare
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 think changing RangeBigDecimal
into (BigDecimal, BigDecimal, Option<BigDecimal>)
could work. With something like this logic:
- If the start or increment is
inf
or-inf
, abort. GNU seq supports it but it's not really useful for anything. - If the end is
inf
and the increment is positive or the end is-inf
and the increment is negative set the end toNone
and just loop endlessly. - If the end is
-inf
and the increment is negative or the end isinf
and the increment is positive, stop immediately without any output.
I created separate pull requests for two of the suggested changes and made all of the suggested changes except:
I'll try that next. Thanks. |
I'm going to approach this from a different angle. I'll open a new pull request when I have something. Thanks for the feedback on this. |
This pull request fixes a floating-point precision issue with the update in the main loop of
seq
. Before this commit, the behavior waswhich was incorrect: -0.2 should be printed as well. This was happening
because the update in the main loop was essentially
which caused
value
to become-0.20000000000000004
. That exceeds the lower bound of -0.2, so that number was not printed. By changing the update towe eliminate this issue.