简体   繁体   English

Rust:Nums 的通用 'within epsilon' 特征

[英]Rust: Generic 'within epsilon' trait for Nums

I'd like to be able to create a function which I can call on Floats or Complex types which returns true when they are within a specified distance from each other.我希望能够创建一个函数,我可以调用 Floats 或 Complex 类型,当它们彼此相距指定距离时返回 true。

This is the closest I got, which of course does not cover Compelx numbers:这是我得到的最接近的,当然不包括 Compelx 数字:

fn eq_within_epsilon<F: Float>(a: F, b:F, eps: F) -> bool {
    F::abs(a - b) < eps
}

I attempted to expand the definition abit, like this, to cover all Num :我试图像这样扩展定义,以涵盖所有Num

trait EqWithinEpsilon {
    fn eq_within_epsilon<T: Num>(a: T, b:T, eps: T) -> bool;
}

impl EqWithinEpsilon for dyn Float {
    fn eq_within_epsilon<T: Num>(a: T, b: T, eps: T) -> bool {
        T::abs(a - b) < eps
    }
}

but I get the error:但我得到了错误:

the trait cannot be made into an object because it uses `Self` as a type parameter

Is there any way I can do this.有什么办法可以做到这一点。

And just in case it comes up, I am using the following crates:以防万一,我正在使用以下板条箱:

num-complex = "0.4.0"
num-traits = "0.2.15"

Implementing a method for dyn Trait is almost never what you want.dyn Trait实现一个方法几乎不是你想要的。 It doesn't implement the method for all types that implement the trait, but rather on the trait itself.它不会为所有实现 trait 的类型实现该方法,而是在 trait 本身上实现。

Usually you would need a blanket implementation ( impl<F: Float> EqWithEpsilon for F ), but in this case it will not work.通常你需要一个全面的实现( impl<F: Float> EqWithEpsilon for F ),但在这种情况下它不起作用。 You need a trait that is common to both Complex and floats.您需要一个对Complex和 float 都通用的特征。 You can write your own:你可以自己写:

trait ComplexFloat: Num {
    type Real: Float;
    fn abs(self) -> Self::Real;
}

// We cannot use a blanket implementation because of coherence.
impl ComplexFloat for f32 {
    type Real = Self;
    fn abs(self) -> Self::Real { self.abs() }
}
impl ComplexFloat for f64 {
    type Real = Self;
    fn abs(self) -> Self::Real { self.abs() }
}

impl<F: Float> ComplexFloat for Complex<F> {
    type Real = F;
    fn abs(self) -> Self::Real { self.norm() }
}

fn eq_within_epsilon<F: ComplexFloat>(a: F, b: F, eps: F::Real) -> bool {
    F::abs(a - b) < eps
}

If you use the very last version of num_traits , 0.4.2 (it wasn't even released to the playground yet, at the time of writing), you can use a ready trait: ComplexFloat .如果您使用num_traits的最新版本 0.4.2(在撰写本文时,它甚至还没有发布到操场上),您可以使用现成的 trait: ComplexFloat

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

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