Rust 中带有整数和浮点数的泛型函数的问题。在 Rust 中研究计算机程序的结构和解释
Problem with Generic Function in Rust with integers and floats. Working through Structure and Interpretation of Computer Programs in Rust
到目前为止我有这个。而且我找不到处理与 good_enough
的比较的方法。我正在研究计算机程序的结构和解释,我想尽我所能地遵守书中的做法。计划很容易。我知道了。只需要帮助使我的 Rust 代码更通用。
游乐场:Rust Playground
use num_traits::cast::FromPrimitive;
use std::cmp::PartialOrd;
use std::ops::{Add, Div, Mul, Sub};
fn square<T: Mul<Output = T> + Copy>(x: T) -> T {
x * x
}
fn average<T: Add<Output = T> + Div<Output = T> + FromPrimitive>(x: T, y: T) -> T {
(x + y) / FromPrimitive::from_usize(2).unwrap()
}
fn abs<T: PartialOrd + Mul<Output = T> + FromPrimitive>(x: T) -> T {
if x < FromPrimitive::from_usize(0).unwrap() {
x * FromPrimitive::from_isize(-1).unwrap()
} else {
x
}
}
fn good_enough<T: Copy + Sub<Output = T> + Mul<Output = T> + FromPrimitive + PartialOrd>(guess: T, x: T) -> bool {
abs(square(guess) - x) < 0.0001
}
fn main() {
println!("Average or {} and {} is {}", 4, 2, average(4, 2));
println!("Square of {} is {}", average(4, 2), square(average(4, 2)));
println!("Absolute Value of {} is {}", -4.5, abs(-4.5));
println!("Test of good_enough: {}",good_enough(3,9));
}
错误:
error[E0308]: mismatched types
--> src/main.rs:22:30
|
21 | fn good_enough<T: Copy + Sub<Output = T> + Mul<Output = T> + FromPrimitive + PartialOrd>(guess: T, x: T) -> bool {
| - this type parameter
22 | abs(square(guess) - x) < 0.0001
| ^^^^^^ expected type parameter `T`, found floating-point number
|
= note: expected type parameter `T`
found type `{float}`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `sqrt`.
已为对计算机程序的结构和解释(第 001 章)感兴趣的人完成 sqrt 项目!
use std::cmp::PartialOrd;
use std::convert::Into;
use std::ops::{Add, Div, Mul, Sub};
use num_traits::cast::FromPrimitive;
fn square<T>(x: T) -> T
where T: Mul<Output=T> + Copy
{
x * x
}
fn average<T>(x: T, y: T) -> T
where T: Add<Output=T> + Div<Output=T> + FromPrimitive
{
(x + y) / FromPrimitive::from_usize(2).unwrap()
}
fn abs<T>(x: T) -> T
where T: PartialOrd + Mul<Output=T> + FromPrimitive
{
if x < FromPrimitive::from_usize(0).unwrap() {
x * FromPrimitive::from_isize(-1).unwrap()
} else {
x
}
}
fn improve<T>(guess: T, x: T) -> T
where T: Add<Output=T> + Div<Output=T> + FromPrimitive + Copy
{
average(guess, x / guess)
}
fn good_enough<T:>(guess: T, x: T) -> bool
where T: Copy + Sub<Output=T> + Mul<Output=T> + FromPrimitive + PartialOrd + Into<f64>
{
let new_guess = guess.into();
let y = x.into();
abs(square(new_guess) - y) <= FromPrimitive::from_f64(0.00000000000001).unwrap()
}
fn sqrt_iter<T>(guess: T, x: T) -> f64
where T: Copy + Add<Output=T> + Div<Output=T> + Mul<Output=T> + Sub<Output=T> + PartialOrd + FromPrimitive + Into<f64>
{
let mut updated_guess = guess.into();
// loop only because I had some stack overflows during testing
let y = x.into();
loop {
if good_enough(updated_guess, y) {
return updated_guess;
} else {
updated_guess = improve(updated_guess, y);
}
}
}
fn my_sqrt<T>(x: T) -> f64
where T: Copy + Add<Output=T> + Div<Output=T> + Mul<Output=T> + Sub<Output=T> + PartialOrd + FromPrimitive + Into<f64>
{
sqrt_iter(FromPrimitive::from_f64(1.0).unwrap(), x)
}
fn main() {
println!("Average or {} and {} is {}", 4, 2, average(4, 2));
println!("Square of {} is {}", average(4, 2), square(average(4, 2)));
println!("Absolute Value of {} is {}", -4.5, abs(-4.5));
println!("Test of good_enough: {}", good_enough(3, 9));
println!("See improve in action guess: {} x:{} outcome:{}", 2, 9, improve(2, 9));
println!("Sqrt of {} is {}", 7921, my_sqrt(7921));
}
输出:
Average or 4 and 2 is 3
Square of 3 is 9
Absolute Value of -4.5 is 4.5
Test of good_enough: true
See improve in action guess: 2 x:9 outcome:3
Sqrt of 7921 is 89
完成的游乐场:Final Playground!
fn good_enough<T: Copy + Sub<Output = T> + Mul<Output = T> + FromPrimitive + PartialOrd>(guess: T, x: T) -> bool {
abs(square(guess) - x) < FromPrimitive::from_f64(0.0001).unwrap()
}
您需要将 0.0001
转换为 T
因为 T
仅实现 PartialOrd
.
或者你可以制作 T: PartialOrd<f64>
但它会使函数无法接受整数类型。
到目前为止我有这个。而且我找不到处理与 good_enough
的比较的方法。我正在研究计算机程序的结构和解释,我想尽我所能地遵守书中的做法。计划很容易。我知道了。只需要帮助使我的 Rust 代码更通用。
游乐场:Rust Playground
use num_traits::cast::FromPrimitive;
use std::cmp::PartialOrd;
use std::ops::{Add, Div, Mul, Sub};
fn square<T: Mul<Output = T> + Copy>(x: T) -> T {
x * x
}
fn average<T: Add<Output = T> + Div<Output = T> + FromPrimitive>(x: T, y: T) -> T {
(x + y) / FromPrimitive::from_usize(2).unwrap()
}
fn abs<T: PartialOrd + Mul<Output = T> + FromPrimitive>(x: T) -> T {
if x < FromPrimitive::from_usize(0).unwrap() {
x * FromPrimitive::from_isize(-1).unwrap()
} else {
x
}
}
fn good_enough<T: Copy + Sub<Output = T> + Mul<Output = T> + FromPrimitive + PartialOrd>(guess: T, x: T) -> bool {
abs(square(guess) - x) < 0.0001
}
fn main() {
println!("Average or {} and {} is {}", 4, 2, average(4, 2));
println!("Square of {} is {}", average(4, 2), square(average(4, 2)));
println!("Absolute Value of {} is {}", -4.5, abs(-4.5));
println!("Test of good_enough: {}",good_enough(3,9));
}
错误:
error[E0308]: mismatched types
--> src/main.rs:22:30
|
21 | fn good_enough<T: Copy + Sub<Output = T> + Mul<Output = T> + FromPrimitive + PartialOrd>(guess: T, x: T) -> bool {
| - this type parameter
22 | abs(square(guess) - x) < 0.0001
| ^^^^^^ expected type parameter `T`, found floating-point number
|
= note: expected type parameter `T`
found type `{float}`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `sqrt`.
已为对计算机程序的结构和解释(第 001 章)感兴趣的人完成 sqrt 项目!
use std::cmp::PartialOrd;
use std::convert::Into;
use std::ops::{Add, Div, Mul, Sub};
use num_traits::cast::FromPrimitive;
fn square<T>(x: T) -> T
where T: Mul<Output=T> + Copy
{
x * x
}
fn average<T>(x: T, y: T) -> T
where T: Add<Output=T> + Div<Output=T> + FromPrimitive
{
(x + y) / FromPrimitive::from_usize(2).unwrap()
}
fn abs<T>(x: T) -> T
where T: PartialOrd + Mul<Output=T> + FromPrimitive
{
if x < FromPrimitive::from_usize(0).unwrap() {
x * FromPrimitive::from_isize(-1).unwrap()
} else {
x
}
}
fn improve<T>(guess: T, x: T) -> T
where T: Add<Output=T> + Div<Output=T> + FromPrimitive + Copy
{
average(guess, x / guess)
}
fn good_enough<T:>(guess: T, x: T) -> bool
where T: Copy + Sub<Output=T> + Mul<Output=T> + FromPrimitive + PartialOrd + Into<f64>
{
let new_guess = guess.into();
let y = x.into();
abs(square(new_guess) - y) <= FromPrimitive::from_f64(0.00000000000001).unwrap()
}
fn sqrt_iter<T>(guess: T, x: T) -> f64
where T: Copy + Add<Output=T> + Div<Output=T> + Mul<Output=T> + Sub<Output=T> + PartialOrd + FromPrimitive + Into<f64>
{
let mut updated_guess = guess.into();
// loop only because I had some stack overflows during testing
let y = x.into();
loop {
if good_enough(updated_guess, y) {
return updated_guess;
} else {
updated_guess = improve(updated_guess, y);
}
}
}
fn my_sqrt<T>(x: T) -> f64
where T: Copy + Add<Output=T> + Div<Output=T> + Mul<Output=T> + Sub<Output=T> + PartialOrd + FromPrimitive + Into<f64>
{
sqrt_iter(FromPrimitive::from_f64(1.0).unwrap(), x)
}
fn main() {
println!("Average or {} and {} is {}", 4, 2, average(4, 2));
println!("Square of {} is {}", average(4, 2), square(average(4, 2)));
println!("Absolute Value of {} is {}", -4.5, abs(-4.5));
println!("Test of good_enough: {}", good_enough(3, 9));
println!("See improve in action guess: {} x:{} outcome:{}", 2, 9, improve(2, 9));
println!("Sqrt of {} is {}", 7921, my_sqrt(7921));
}
输出:
Average or 4 and 2 is 3
Square of 3 is 9
Absolute Value of -4.5 is 4.5
Test of good_enough: true
See improve in action guess: 2 x:9 outcome:3
Sqrt of 7921 is 89
完成的游乐场:Final Playground!
fn good_enough<T: Copy + Sub<Output = T> + Mul<Output = T> + FromPrimitive + PartialOrd>(guess: T, x: T) -> bool {
abs(square(guess) - x) < FromPrimitive::from_f64(0.0001).unwrap()
}
您需要将 0.0001
转换为 T
因为 T
仅实现 PartialOrd
.
或者你可以制作 T: PartialOrd<f64>
但它会使函数无法接受整数类型。