将ASCII数字标准化为数字

时间:2015-02-28 03:56:52

标签: ascii rust bytestring

正在运行示例:http://is.gd/NBpvmH

fn main() {
    show({
        let number = b"123456";
        for sequence in number.windows(6) {
            let product = sequence.iter().fold(1, |a, &b| a * (b as u64));
            println!("product of {:?} is {}", sequence, product);
        }
    });
}

而不是像[49,50,51,52,53,54]的产品那样的输出是15312500000“我需要括号中的正常数字和产品的标准化结果。 尝试使用- b'0'减去48以获得第5行中的正常数字不起作用,即

a * ((b as u64) -b'0')

(a - b'0') * (b as u64)

似乎我在这里遗漏了一些东西,例如我不知道fold()中的'a'和'b'值究竟是什么。任何人都可以开导我吗? :)

2 个答案:

答案 0 :(得分:3)

查看the signature of fold,我们可以看到它需要两个参数:

fn fold<B, F>(self, init: B, f: F) -> B
   where F: FnMut(B, Self::Item) -> B

init,它是一些任意类型Bf,它是一个闭包,它从迭代器中获取B值和一个元素,按顺序计算新的B值。整个函数返回B。这些类型强烈暗示会发生什么:在迭代器的连续元素上重复调用闭包f,将计算的B值传递给下一个f调用。检查the implementation证实了这种怀疑:

let mut accum = init;
for x in self {
    accum = f(accum, x);
}
accum

它遍历迭代器,将累积状态传递给闭包,以便计算下一个状态。

首先,让我们把类型放在fold电话上:

let product = sequence.iter().fold(1, |a: u64, &b: &u8| a * (b as u64));

也就是说,我们想要的B类型是u64(这是我们最终产品的类型),迭代器的项类型是&u8,引用一个字节。

现在,我们可以手动内联fold的定义来计算product,以尝试澄清所需的行为(我现在忽略了规范化):

let mut accum = 1;
for x in sequence.iter() {
    accum = { // the closure
        let a: u64 = accum;
        let &b: &u8 = x;
        a * b as u64
    }
}
let product = accum;

简化:

let mut product = 1;
for &b in sequence.iter() {
    product = product * (b as u64)
}

希望这更清楚地说明需要发生的事情:b遍历每个字节,因此需要调整的值是将ASCII编码值降低到预期的0..10范围。 / p>

所以,你是对的:

a * ((b as u64) -b'0')

但是,细节意味着无法编译,类型错误:b'0'类型为u8b as u64类型为u64,而且&#39;将-u64u8一起使用是不合法的。将标准化移至u64演员阵容之前将确保此操作正常,因为您将减去bu8}和u8

product * (b - b'0') as u64

总而言之,fold可能看起来更清晰(实际上是工作):

let product = sequence.iter()
    .fold(1, |prod, &byte| prod * (byte - b'0') as u64);

(我为在IRC上给你这么令人困惑的代码而道歉。)

答案 1 :(得分:0)

作为fold的替代方案,您可以使用mapMultiplicativeIterator::product。我发现这两个步骤有助于更清楚地了解正在发生的事情。

#![feature(core)]

use std::iter::MultiplicativeIterator;

fn main() {
    let number = b"123456";
    for sequence in number.windows(6) {
        let product = sequence.iter().map(|v| (v - b'0') as u64).product();
        println!("product of {:?} is {}", sequence, product);
    }
}

您甚至可以选择将调整大小从u8拆分为u64

sequence.iter().map(|v| v - b'0').map(|v| v as u64).product();