How can I store the minimum value of i32 in a variable?
// Java Example :
int min = Integer.MIN_VALUE;
// C++ example
int min = INT_MIN;
I want to do something like:
let min: i32 = i32_MIN_VALUE;
You have some const defined:
MIN
MAX
let min: u32 = u32::MIN;
They are also defined for other primitive numeric types.
Related
I have a bit of of a problem regarding types in rust.
In my problem, I am simulating message transferring in a graph.
I have the speed at which a message can be transferred in M/s (Megabits/seconds) along a channel and I also have the message size in M (Megabits). To get the time at which the message arrive is pretty standard: size/speed.
I am now trying to get the difference in time in nanoseconds between the time that the message was sent and the time now. I want it in nanoseconds because if the message is very small then the time for transferring will also be very small.
If I want to get number of milliseconds from the difference in time then I can get it with the function diff.num_milliseconds() which gives me a i64 type.
However if I want to get the number of nanoseconds from the difference then diff.num_nanoseconds() returns a type Option<i64> and you can't seem to compare a float with Option<i64>.
use std::thread;
use std::time::Duration;
use chrono::{Utc};
fn main() {
// size of message in M
let size = 0.05;
// transfer speed in M/s
let speed = 1e6;
// speed in M/ns
let speed_nano = speed/1e9;
let now = Utc::now();
let sec = Duration::from_millis(5000);
thread::sleep(sec);
let then = Utc::now();
let diff = then-now;
println!("{}",(size/speed_nano) < diff.num_nanoseconds());
}
What am I missing here? How can I properly do the comparison?
Option<i64> means that the function returns a value that contains either an i64 or nothing at all. You get either a Some(an_i64) or None, which represents the absence of an i64 value.
You can extract the i64 (if it's there) using unwrap, for example:
(size/speed_nano) < diff.num_nanoseconds().unwrap()
If there's no i64 value there, unwrap will panic and terminate your program. You can also use unwrap_or to supply a default value:
(size/speed_nano) < diff.num_nanoseconds().unwrap_or(0)
You can't compare a float to an Option<i64> because it doesn't make sense: how would a float compare to a missing, "nonexistent" value None?
fn is_less(a: f64, b: Option<i64>) -> bool {
match b {
Some(my_integer) => a < my_integer,
None => ?????
}
}
In that case, the float a is not less than None, but it's also not equal to it and not greater, so what is it? Rust decided that it's an error.
I have an f32 value that I'd like to print. Being a float, I can represent integers with this type as well
let a_float: f32 = 3.0;
let another_float: f32 = 3.14;
// let's pretend this was user input,
// we didn't know what they'd put enter, so we used f32 to cover our bases
let an_integer: f32 = 3;
I'd like to print a value stored as an f32 with a minimum amount of precision, but using as much as necessary to represent the value stored. If my desired minimum precision was one (1), I'd expect the following transformation to be done on the float:
let a_float: f32 = 3.0; // print 3.0
let another_float: f32 = 3.14; // print 3.14
let an_integer: f32 = 3; // print 3.0
I know that I can set a finite number of decimal places using std::fmt's precision, but that doesn't seem to give me what I want. Is there a way to achieve this functionality without bringing in additional formatting crates? Pulling in additional crates isn't out of the realm of possibility, I'm moreso interested in what I'm able to do 'out of the box'
Rust already does this by default. Every float is printed with as many digits as are necessary to denote that particular float uniquely.
Here's a program to demonstrate this. It generates 10000 random floats, converts them to strings, and checks how many digits can be deleted from the fractional part without changing the value.
(Caveat: This does not show that there aren't cases where the number could be represented in fewer digits by rounding it in a different direction, which can happen sometimes if I remember correctly. I'm not a float formatting expert.)
use std::collections::HashMap;
use rand::{Rng, thread_rng};
/// Change this to choose the type analyzed
type Float = f32;
fn main() {
let mut rng = thread_rng();
let mut digit_histogram = HashMap::new();
for _ in 1..10000 {
let x: Float = rng.gen_range(0.0..10.0);
let string = x.to_string();
// Break up string representation
let before_exponent_pos = string.find('e').unwrap_or(string.len());
let after_decimal_pos = string.find('.')
.map(|p| p + 1)
.unwrap_or(before_exponent_pos);
let prefix = &string[..after_decimal_pos];
let mut fractional_digits = &string[after_decimal_pos..before_exponent_pos];
let suffix = &string[before_exponent_pos..];
// What happens if we truncate the digits?
let initial_digits = fractional_digits.len();
let mut unnecessary_digits = 0;
while fractional_digits.len() > 0 {
fractional_digits = &fractional_digits[..fractional_digits.len() - 1];
let shortened_string = format!("{}{}{}",
prefix,
fractional_digits,
suffix,
);
let shortened_x = shortened_string.parse::<Float>().unwrap();
if shortened_x == x {
unnecessary_digits += 1;
} else {
break;
}
}
*(digit_histogram
.entry((initial_digits, unnecessary_digits))
.or_insert(0)) += 1;
}
// Summarize results.
let mut digit_histogram = digit_histogram.into_iter().collect::<Vec<_>>();
digit_histogram.sort_by_key(|pair| pair.0);
for ((initial_digits, unnecessary_digits), occurrences) in digit_histogram {
println!(
"{} digits with {} unnecessary × {}",
initial_digits,
unnecessary_digits,
occurrences);
}
}
Runnable on Rust Playground. Results:
2 digits with 0 unnecessary × 1
3 digits with 0 unnecessary × 6
4 digits with 0 unnecessary × 25
5 digits with 0 unnecessary × 401
6 digits with 0 unnecessary × 4061
7 digits with 0 unnecessary × 4931
8 digits with 0 unnecessary × 504
9 digits with 0 unnecessary × 62
10 digits with 0 unnecessary × 8
The program saw a wide variety of numbers of digits, but never any that could be deleted without changing the answer.
Pretty print got me what I was looking for
fn main() {
let a_float: f32 = 3.0; // print 3.0
let another_float: f32 = 3.14; // print 3.14
let an_integer: i32 = 3; // print 3.0
println!("{:?}", a_float);
println!("{:?}", another_float);
println!("{:?}", an_integer as f32);
}
Say I have something like this:
let SIZE = 100;
let a = [0; SIZE];
let b = -1;
How can I then do something like:
a[(SIZE/2)+b];
There's a mismatch here between the usize index of the array and the i32 of the negative number being subtracted. Is there a convenient way of indexing through an array also with negative offsets?
Like #Aplet123 answered, you may use casts. But if b is always negative, you could save the absolute value and just substact it instead:
let b = 1;
return a[SIZE/2 - b];
Cast it to an isize (a signed integer with the same size as a usize) first:
a[((SIZE / 2) as isize + b) as usize]
I am working on parsing OpenType font files, and need to parse (and write) two kind of fixed-point numbers:
16-bit signed fixed number with the low 14 bits of fraction (2.14)
32-bit signed fixed-point number (16.16)
I assume that, in the end, it should be cast to/from f32
The OpenType Spec describes:
The F2DOT14 format consists of a signed, 2’s complement integer and an
unsigned fraction. To compute the actual value, take the integer and
add the fraction.
Examples of 2.14 values are:
Decimal Value Hex Value Integer Fraction
1.999939 0x7fff 1 16383/16384
1.75 0x7000 1 12288/16384
0.000061 0x0001 0 1/16384
0.0 0x0000 0 0/16384
-0.000061 0xffff -1 16383/16384
-2.0 0x8000 -2 0/16384
I have a solution that works but only for 2.14 values:
fn from(number: u16) -> f32 {
let mut int = (number >> 14) as f32;
if int > 1f32 {
int -= 4f32;
}
let frac = (number & 0b11_1111_1111_1111) as f32 / 16384 as f32;
int + frac
}
Because the integer value should be [-2, 2), I subtract 4 if the parsed integer is higher than 1 to achieve the negative numbers.
I am looking for a way of doing this for a any possible split of fixed-point numbers (like 2.14, 16.16, 3.5, 24.40, etc.) inside the standard range of Rust integer primitive types (u16, u32, u64, etc.).
Was able to solve my issue, here is an example of parsing 16-bit fixed point number:
use std::mem::size_of;
fn from_u16(raw: u16, frac_count: usize) -> f32 {
let bit_count = size_of::<u16>() * 8;
let int_count = bit_count - frac_count;
let unsigned = (raw >> frac_count) as isize;
let sign_bit = unsigned >> (int_count - 1) & 1;
let high_bits = if sign_bit == 1 { -1 } else { 0 };
let signed = high_bits << int_count | unsigned as isize;
let mut mask = 0;
for i in 0..=frac_count {
mask = mask << i | 1;
}
let frac = (raw & mask) as f32 / (1 << frac_count) as f32;
signed as f32 + frac
}
So I'm trying to get a random number, but I'd rather not have it come back as uint instead of int... Not sure if this match is right, either, but the compiler doesn't get that far because it's never heard of this from_uint thing I'm trying to do:
fn get_random(max: &int) -> int {
// Here we use * to dereference max
// ...that is, we access the value at
// the pointer location rather than
// trying to do math using the actual
// pointer itself
match int::from_uint(rand::random::<uint>() % *max + 1) {
Some(n) => n,
None => 0,
}
}
from_uint is not in the namespace of std::int, but std::num: http://doc.rust-lang.org/std/num/fn.from_uint.html
Original answer:
Cast a u32 to int with as. If you cast uint or u64 to int, you risk overflowing into the negatives (assuming you are on 64 bit). From the docs:
The size of a uint is equivalent to the size of a pointer on the particular architecture in question.
This works:
use std::rand;
fn main() {
let max = 42i;
println!("{}" , get_random(&max));
}
fn get_random(max: &int) -> int {
(rand::random::<u32>() as int) % (*max + 1)
}