mirror of
https://github.com/nushell/nushell
synced 2024-12-26 13:03:07 +00:00
f738932bbd
# Description This PR changes the range contains logic to take the step into account. ```nushell # before 2 in 1..3.. # true # now 2 in 1..3.. # false ``` --- I encountered another issue while adding tests. Due to floating point precision, `2.1 in 1..1.1..3` will return `false`. The floating point error is even bigger than `f64::EPSILON` (`0.09999999999999876` vs `2.220446049250313e-16`). This issue disappears with bigger numbers. I tried a different algorithm (checking if the estimated number of steps is close enough to any integer) but the results are still pretty bad: ```rust let n_steps = (value - self.start) / self.step; // 14.999999999999988 (n_steps - n_steps.round()).abs() < f64::EPSILON // returns false ``` Maybe it can be shipped like this, the REPL already has floating point errors (`1.1 - 1` returns `0.10000000000000009`). Or maybe there's a way to fix this that I didn't think of. I'm open to ideas! But in any case performing this kind of checks on a range of floats seems more niche than doing it on a range of ints. # User-Facing Changes Code that depended on this behavior to check if a number is between `start` and `end` will potentially return a different value. # Tests + Formatting # After Submitting
76 lines
1.5 KiB
Rust
76 lines
1.5 KiB
Rust
use crate::repl::tests::{fail_test, run_test, TestResult};
|
|
|
|
#[test]
|
|
fn int_in_inc_range() -> TestResult {
|
|
run_test(r#"1 in -4..9.42"#, "true")
|
|
}
|
|
|
|
#[test]
|
|
fn int_in_dec_range() -> TestResult {
|
|
run_test(r#"1 in 9..-4.42"#, "true")
|
|
}
|
|
|
|
#[test]
|
|
fn int_in_exclusive_range() -> TestResult {
|
|
run_test(r#"3 in 0..<3"#, "false")
|
|
}
|
|
|
|
#[test]
|
|
fn float_in_inc_range() -> TestResult {
|
|
run_test(r#"1.58 in -4.42..9"#, "true")
|
|
}
|
|
|
|
#[test]
|
|
fn float_in_dec_range() -> TestResult {
|
|
run_test(r#"1.42 in 9.42..-4.42"#, "true")
|
|
}
|
|
|
|
#[test]
|
|
fn non_number_in_range() -> TestResult {
|
|
fail_test(r#"'a' in 1..3"#, "subset comparison is not supported")
|
|
}
|
|
|
|
#[test]
|
|
fn float_not_in_inc_range() -> TestResult {
|
|
run_test(r#"1.4 not-in 2..9.42"#, "true")
|
|
}
|
|
|
|
#[test]
|
|
fn range_and_reduction() -> TestResult {
|
|
run_test(r#"1..6..36 | math sum"#, "148")
|
|
}
|
|
|
|
#[test]
|
|
fn zip_ranges() -> TestResult {
|
|
run_test(r#"1..3 | zip 4..6 | get 2.1"#, "6")
|
|
}
|
|
|
|
#[test]
|
|
fn int_in_stepped_range() -> TestResult {
|
|
run_test(r#"7 in 1..3..15"#, "true")
|
|
}
|
|
|
|
#[test]
|
|
fn int_in_unbounded_stepped_range() -> TestResult {
|
|
run_test(r#"1000001 in 1..3.."#, "true")
|
|
}
|
|
|
|
#[test]
|
|
fn int_not_in_unbounded_stepped_range() -> TestResult {
|
|
run_test(r#"2 in 1..3.."#, "false")
|
|
}
|
|
|
|
#[test]
|
|
fn float_in_stepped_range() -> TestResult {
|
|
run_test(r#"5.5 in 1..1.5..10"#, "true")
|
|
}
|
|
|
|
#[test]
|
|
fn float_in_unbounded_stepped_range() -> TestResult {
|
|
run_test(r#"100.5 in 1..1.5.."#, "true")
|
|
}
|
|
|
|
#[test]
|
|
fn float_not_in_unbounded_stepped_range() -> TestResult {
|
|
run_test(r#"2.1 in 1.2..3.."#, "false")
|
|
}
|