Ebadta
Ebadta

Reputation: 367

BTreeMap of f64's

I would like to have a sorted array which has an f64 as key and an f64 as value. I need to update, delete and insert to this array by finding the right key. I need to get the first 1000 sorted entries, and also the first entry. These operations must be fast.

By reading the documentation, I thought BTreeMap is good for me.

However, when I try to insert into it I got this error message:

the trait bound `f64: Ord` is not satisfied
the trait `Ord` is not implemented for `f64`rustcE0277

What is the recommended way to do this with Rust?

My code:

use std::collections::BTreeMap;

pub struct MyStruct {
  pub map: BTreeMap<f64, f64>
}

impl MyStruct {
  pub fn new() -> MyStruct {
    MyStruct {
      map: BTreeMap::new()
    }
  }
}

fn main() {
    let mut my_struct = MyStruct::new();
    my_struct.map.insert(1.0, 2.0);
}

Upvotes: 5

Views: 1587

Answers (3)

Serhii Potapov
Serhii Potapov

Reputation: 3970

You can use nutype crate.

With nutype you can add finite validation on your newtype, which excludes NaN and Infinity. This allows to derive Eq and Ord:

use nutype::nutype;
use std::collections::BTreeMap;

#[nutype(
    validate(finite),
    derive(Debug, PartialEq, Eq, PartialOrd, Ord),
)]
pub struct Float(f64);

#[derive(Debug)]
pub struct MyStruct {
  pub map: BTreeMap<Float, Float>
}

impl MyStruct {
  pub fn new() -> MyStruct {
    MyStruct {
      map: BTreeMap::new()
    }
  }
}

fn main() {
    let mut my_struct = MyStruct::new();
    let one = Float::new(1.0).unwrap();
    let two = Float::new(2.0).unwrap();
    my_struct.map.insert(one, two);

    println!("{my_struct:?}");
}

Output:

MyStruct { map: {Float(1.0): Float(2.0)} }

Upvotes: 0

BallpointBen
BallpointBen

Reputation: 13750

I think you may be looking for the ordered_float crate and either the OrderedFloat (can store NaN, sorts it above +inf) or NotNan (cannot store NaN) structs, which both are a float-like type that is Eq and Ord (in violation of the IEEE standard).

Upvotes: 7

Dev611
Dev611

Reputation: 89

Floating point numbers are not good candidates for keys. Maybe you should consider converting them to integers or strings. For example, if you only care about 2 digits after the decimal separator, you can do something like n*100, rounded and converted to an integer type.

Upvotes: 2

Related Questions