I have the following closure.
let ss = aa.iter().fold(0., |sum: f32,x| if *x != f32::NAN { sum + e } else { sum + 0. })
I am trying to sum all the values omitting f32::NAN
if any in the vector(I have couple of NaN
values in the vector).
But, My return gives me NaN
value because my condition if *x != f32::NAN
does not seem to be valid. Because, the following closure yields the original vector instead of omitting NaN
value.
let bb = aa.iter().filter(|x| **x != f32::NAN).map(|x| x)
My question is, how do I match f32::NAN
value in a if
condition? In a broader perspective, How do I omit NaN
values in a vector?
You cannot check for NaN that way, since NaN == NaN
evaluates to false
. Use f32::is_nan
instead. Furthermore, you can use Iterator::filter
to filter out elements of an iterator and Iterator::sum
to sum all values.
This results in this code ( Playground ):
let aa = [3.14f32, std::f32::NAN, 2.71, 27.99];
let ss = aa.iter()
.filter(|n| !n.is_nan())
.sum::<f32>();
println!("{}", ss);
With the right directional help of Warren Weckesser
Managed to make the closure work.
Here is the solution for those who might need.
let ss = aa.iter().fold(0., |sum: f32, x| if x.is_nan() { sum + 0. } else { sum + x });
Alternatively,
let ss = aa.iter().fold(0., |sum: f32, x| if x.is_nan() { sum } else { sum + x });
if one cares about a unnecessary +
operation.
Performance Comparison
extern crate rand;
use rand::Rng;
fn main() {
let mut a [f32; 1000] = [0.; 1000];
for i in 0..1000 {
a[i] = rand::thread_rng().gen_range(1,11);
}
}
Approach-I:
let ss = a.iter()
.filter(|n| !n.is_nan())
.sum::<f32>();
Callgrind
>> cargo profiler callgrind -n 10
Compiling playground in debug mode...
Profiling playground with callgrind...
Total Instructions...3,959,454
177,532 (4.5%) isaac64.rs:rand::prng::isaac64::Isaac64Rng::isaac64
-----------------------------------------------------------------------
121,742 (3.1%) memmove-vec-unaligned-erms.S:memcpy@GLIBC_2.2.5
-----------------------------------------------------------------------
104,224 (2.6%) dl-lookup.c:do_lookup_x
-----------------------------------------------------------------------
102,982 (2.6%) ptr.rs:core::ptr::swap_nonoverlapping_one
-----------------------------------------------------------------------
99,660 (2.5%) intrinsics.rs:core::intrinsics::copy_nonoverlapping
-----------------------------------------------------------------------
76,555 (1.9%) strcmp.S:strcmp
-----------------------------------------------------------------------
72,997 (1.8%) local.rs:_..std..thread..local..LocalKey..T....::try_with
-----------------------------------------------------------------------
72,063 (1.8%) ptr.rs:_..core..ptr..NonNull..T....::as_ref
-----------------------------------------------------------------------
70,028 (1.8%) rc.rs:alloc::rc::RcBoxPtr::strong
-----------------------------------------------------------------------
62,000 (1.6%) ptr.rs:core::ptr::swap_nonoverlapping_one
-----------------------------------------------------------------------
Approach-II:
let ss = a.iter()
.fold(0., |sum: f32, x| if x.is_nan() { sum } else { sum + x });
Callgrind
>> cargo profiler callgrind -n 10
Compiling playground in debug mode...
Profiling playground with callgrind...
Total Instructions...3,938,312
177,532 (4.5%) isaac64.rs:rand::prng::isaac64::Isaac64Rng::isaac64
-----------------------------------------------------------------------
121,766 (3.1%) memmove-vec-unaligned-erms.S:memcpy@GLIBC_2.2.5
-----------------------------------------------------------------------
104,224 (2.6%) dl-lookup.c:do_lookup_x
-----------------------------------------------------------------------
102,982 (2.6%) ptr.rs:core::ptr::swap_nonoverlapping_one
-----------------------------------------------------------------------
99,660 (2.5%) intrinsics.rs:core::intrinsics::copy_nonoverlapping
-----------------------------------------------------------------------
76,555 (1.9%) strcmp.S:strcmp
-----------------------------------------------------------------------
72,997 (1.9%) local.rs:_..std..thread..local..LocalKey..T....::try_with
-----------------------------------------------------------------------
72,063 (1.8%) ptr.rs:_..core..ptr..NonNull..T....::as_ref
-----------------------------------------------------------------------
70,028 (1.8%) rc.rs:alloc::rc::RcBoxPtr::strong
-----------------------------------------------------------------------
62,000 (1.6%) ptr.rs:core::ptr::swap_nonoverlapping_one
-----------------------------------------------------------------------
Looking at the Total Instructions , Approach-II fares well in terms of run-time performance with ~20,000
instructions less than Approach-I for 1000
element array. Anticipating this difference will positively translate in to enhanced run-time performance for Approach-II . Investigating, from where the difference stem from.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.