1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

seq: Accept underflow in parameters

Also, add a test to check that a very, very, small number is
treated as 0. That's probably undefined behaviour, but it does
make some sense.
This commit is contained in:
Nicolas Boichat 2025-03-21 21:25:04 +01:00 committed by Daniel Hofstetter
parent 686f1c7841
commit 84e5ee4b86
2 changed files with 21 additions and 3 deletions

View file

@ -11,7 +11,7 @@ use std::str::FromStr;
use bigdecimal::BigDecimal; use bigdecimal::BigDecimal;
use num_traits::Zero; use num_traits::Zero;
use uucore::format::num_parser::ExtendedParser; use uucore::format::num_parser::{ExtendedParser, ExtendedParserError};
use crate::number::PreciseNumber; use crate::number::PreciseNumber;
use uucore::format::ExtendedBigDecimal; use uucore::format::ExtendedBigDecimal;
@ -61,8 +61,9 @@ fn compute_num_integral_digits(input: &str, _number: &BigDecimal) -> usize {
// If there is an exponent, reparse that (yes this is not optimal, // If there is an exponent, reparse that (yes this is not optimal,
// but we can't necessarily exactly recover that from the parsed number). // but we can't necessarily exactly recover that from the parsed number).
if parts.len() == 2 { if parts.len() == 2 {
let exp = parts[1].parse::<i64>().unwrap(); let exp = parts[1].parse::<i64>().unwrap_or(0);
// For positive exponents, effectively expand the number. Ignore negative exponents. // For positive exponents, effectively expand the number. Ignore negative exponents.
// Also ignore overflowed exponents (default 0 above).
if exp > 0 { if exp > 0 {
digits + exp as usize digits + exp as usize
} else { } else {
@ -80,6 +81,7 @@ impl FromStr for PreciseNumber {
fn from_str(input: &str) -> Result<Self, Self::Err> { fn from_str(input: &str) -> Result<Self, Self::Err> {
let ebd = match ExtendedBigDecimal::extended_parse(input) { let ebd = match ExtendedBigDecimal::extended_parse(input) {
Ok(ebd) => ebd, Ok(ebd) => ebd,
Err(ExtendedParserError::Underflow(ebd)) => ebd, // Treat underflow as 0
Err(_) => return Err(ParseNumberError::Float), Err(_) => return Err(ParseNumberError::Float),
}; };
@ -95,7 +97,11 @@ impl FromStr for PreciseNumber {
ExtendedBigDecimal::Nan | ExtendedBigDecimal::MinusNan => { ExtendedBigDecimal::Nan | ExtendedBigDecimal::MinusNan => {
return Err(ParseNumberError::Nan); return Err(ParseNumberError::Nan);
} }
ExtendedBigDecimal::BigDecimal(ref bd) => bd.clone(), ExtendedBigDecimal::BigDecimal(ref bd) => {
// TODO: `seq` treats small numbers < 1e-4950 as 0, we could do the same
// to avoid printing senselessly small numbers.
bd.clone()
}
ExtendedBigDecimal::MinusZero => BigDecimal::zero(), ExtendedBigDecimal::MinusZero => BigDecimal::zero(),
}; };

View file

@ -911,6 +911,18 @@ fn test_parse_out_of_bounds_exponents() {
.args(&["1e-9223372036854775808"]) .args(&["1e-9223372036854775808"])
.succeeds() .succeeds()
.stdout_only(""); .stdout_only("");
// GNU seq supports arbitrarily small exponents (and treats the value as 0).
new_ucmd!()
.args(&["1e-922337203685477580800000000", "1"])
.succeeds()
.stdout_only("0\n1\n");
// Check we can also underflow to -0.0.
new_ucmd!()
.args(&["-1e-922337203685477580800000000", "1"])
.succeeds()
.stdout_only("-0\n1\n");
} }
#[ignore] #[ignore]