简体   繁体   English

f32 :: NAN锈封闭的值,以省略“ NaN”值

[英]value of f32::NAN rust closure for omitting 'NaN' values

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). 我试图对所有省略向量f32::NAN的值求和(如果向量中有几个NaN值)。

But, My return gives me NaN value because my condition if *x != f32::NAN does not seem to be valid. 但是,我的返回给了我NaN值,因为if *x != f32::NAN条件似乎无效, if *x != f32::NAN我的条件。 Because, the following closure yields the original vector instead of omitting NaN value. 因为,以下闭包将产生原始向量,而不是忽略NaN值。

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? 我的问题是,如何在if条件下匹配f32::NAN值? In a broader perspective, How do I omit NaN values in a vector? 从更广泛的角度来看,如何在向量中忽略NaN值?

You cannot check for NaN that way, since NaN == NaN evaluates to false . 您不能以这种方式检查NaN,因为NaN == NaN值为false Use f32::is_nan instead. 使用f32::is_nan代替。 Furthermore, you can use Iterator::filter to filter out elements of an iterator and Iterator::sum to sum all values. 此外,您可以使用Iterator::filter过滤掉迭代器的元素,并使用Iterator::sum求和所有值。

This results in this code ( Playground ): 这将产生以下代码( 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. Warren Weckesser的正确指导下, Warren Weckesser使封堵工作。

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: 方法-I:

let ss = a.iter()
        .filter(|n| !n.is_nan())
        .sum::<f32>();

Callgrind 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: 方法-II:

let ss = a.iter()
        .fold(0., |sum: f32, x| if x.is_nan() { sum } else { sum + x });

Callgrind 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. 总指令来看,对于1000元素数组, 方法II在运行时性能方面要好得多,比方法I~20,000条指令。 Anticipating this difference will positively translate in to enhanced run-time performance for Approach-II . 预期这种差异将积极地转化为方法II的增强的运行时性能。 Investigating, from where the difference stem from. 调查,差异源自何处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM