Shanthakumar
Shanthakumar

Reputation: 768

Converting a Bitv to uint

I'm trying to convert a Bitv to uint.

use std::collections::Bitv;
use std::num::Float;

fn main() {
    let mut bv = Bitv::with_capacity(3,false);
    bv.set(2,true); // Set bit 3
    let deci = Vec::from_fn(bv.len(),|i| if bv.get(i) { 
                                    (i as f32).exp2() 
                                    } else { 0f32 }).iter()
                                                    .fold(0u, |acc, &n| acc+n as uint);
    println!["{}",deci] // 4
}   

That works. Though I wanna know if there is any library function that I'm unaware of or is there any other better way to do.

Upvotes: 1

Views: 174

Answers (2)

Shepmaster
Shepmaster

Reputation: 430891

Some transformations of your code I made.

Don't use floats

Rust 1.0

let vec: Vec<_> = (0..bv.len()).map(|i| {
    if bv[i] {
        1 << i
    } else {
        0
    }}).collect();
let deci = vec.iter().fold(0, |acc, &n| acc + n);

Original

let vec = Vec::from_fn(bv.len(), |i| {
    if bv.get(i) {
        1u << i
    } else {
        0u
    }});
let deci = vec.iter().fold(0u, |acc, &n| acc + n);

Don't make an array, just use a tuple

Rust 1.0

let deci = bv.iter()
    .fold((0, 0), |(mut acc, nth), bit| {
        if bit { acc += 1 << nth };
        (acc, nth + 1)
    }).0;

Original

let deci = bv.iter()
    .fold((0u, 0u), |(mut acc, nth), bit| {
        if bit { acc += 1 << nth };
        (acc, nth + 1)
    }).0;

A bit more usage of iterators

Rust 1.0

let deci = bv.iter()
    .enumerate()
    .filter_map(|(nth, bit)| if bit { Some(1 << nth) } else { None })
    .fold(0, |acc, val| acc + val);

Original

let deci = bv.iter()
    .enumerate()
    .filter_map(|(nth, bit)| if bit { Some(1 << nth) } else { None })
    .fold(0u, |acc, val| acc + val);

Ideally, you could reorganize your code to make use of to_bytes, but the order of bits is different from your example.

Upvotes: 2

Francis Gagn&#233;
Francis Gagn&#233;

Reputation: 65782

Bitv doesn't provide a way to return its value as a uint, because the Bitv might contain more bits than a uint does. BTW, the size of uint is architecture-dependant (32 bits on 32-bit systems, 64 bits on 64-bit systems), so you should prefer using u32 or u64 unless you really need a uint.

Bitv provides the to_bytes and to_bools methods, which return a Vec<u8> and a Vec<bool>, respectively. A Vec<u8> is more compact than a Vec<bool>, so to_bytes should be preferred when the Bitv is known to be large (but if it's known to be large, why would you try converting it to a uint?).

We can also iterate on the bits directly by using iter.

use std::collections::Bitv;
use std::mem;

fn main() {
    let mut bv = Bitv::with_capacity(3, false);
    bv.set(2, true); // Set bit 3

    let deci = bv.iter().enumerate().fold(
        0u64,
        |accum, (bit_pos, bit)| {
            if bit {
                assert!(bit_pos < mem::size_of_val(&accum) * 8);
                accum + (1 << bit_pos)
            } else {
                accum
            }
        });

    println!("{}", deci); // 4
}

Upvotes: 2

Related Questions