Решение на Bigint от Ивайло Иванов

Обратно към всички решения

Към профила на Ивайло Иванов

Резултати

  • 13 точки от тестове
  • 0 бонус точки
  • 13 точки общо
  • 13 успешни тест(а)
  • 2 неуспешни тест(а)

Код

use std::{str::FromStr, vec};
#[derive(Debug, Eq)]
pub struct Bigint {
sign: i8,
digits: Vec<u8>,
}
impl Bigint {
pub fn new() -> Self {
Bigint::from_components(1, vec![0])
}
fn from_components(sign: i8, digits: Vec<u8>) -> Self {
Bigint{
sign: sign,
digits: digits
}
}
/// Връща `true` ако числото е положително. Нулата не е положителна.
pub fn is_positive(&self) -> bool {
if self.digits.len() == 1 && self.digits[0] == 0 {
false
}
else if self.sign == 1 {
true
}
else {
false
}
}
/// Връща `true` ако числото е отрицателно. Нулата не е отрицателна.
pub fn is_negative(&self) -> bool {
if self.digits.len() == 1 && self.digits[0] == 0 {
false
}
else if self.sign == -1 {
true
}
else {
false
}
}
fn add_digits(left: Vec<u8>, right: Vec<u8>) -> Vec<u8> {
let mut new_digits = Vec::<u8>::new();
let mut left_iter = left.iter().rev();
let mut right_iter = right.iter().rev();
let mut carry_over = 0;
loop {
match (left_iter.next(), right_iter.next()) {
(Some(x), Some(y)) => {
new_digits.push( (x + y) % 10 + carry_over );
carry_over = (x + y) / 10;
},
(Some(x), None) => new_digits.push( x.clone() ),
(None, Some(y)) => new_digits.push( y.clone() ),
(None, None) => break,
}
}
if carry_over == 1 {
new_digits.push(1);
}
new_digits.reverse();
new_digits
}
fn subtract_digits(larger: Vec<u8>, smaller: Vec<u8>) -> Vec<u8> {
let mut new_digits = Vec::<u8>::new();
let mut left_iter = larger.iter().rev();
let mut right_iter = smaller.iter().rev();
let mut carry_over = 0;
loop {
match (left_iter.next(), right_iter.next()) {
(Some(x), Some(y)) => {
let digit = (*x as i8) - (*y as i8) - (carry_over as i8);
if digit < 0 {
new_digits.push( (digit + 10) as u8 );
carry_over = 1;
}
else {
new_digits.push( digit as u8 );
carry_over = 0;
}
},
(Some(x), None) => {
let digit = (*x as i8) - (carry_over as i8);
if digit < 0 {
new_digits.push( (digit + 10) as u8 );
carry_over = 1;
}
else {
new_digits.push( digit as u8 );
carry_over = 0;
}
},
(None, Some(_)) => unreachable!(),
(None, None) => break,
}
}
new_digits.reverse();
if new_digits[0] == 0 {
let mut i = 0;
while new_digits[i] == 0 {
i += 1
}
new_digits.drain(0..i);
}
new_digits
}
}
#[derive(Debug, PartialEq)]
pub struct ParseError;
impl FromStr for Bigint {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.as_bytes();
if s.is_empty(){
return Ok(Bigint::from_components(1, vec![0]));
}
let (mut sign, mut s) = match s[0] {
b'+' => (1, &s[1..]),
b'-' => (-1, &s[1..]),
_ => (1, s)
};
if s.is_empty() {
return Err(ParseError);
}
else if s.len() == 1 && s[0] == 48{
Ok(Bigint{
sign: 1,
digits: vec![0]
})
}
else {
//consume zeros infront of number
while !s.is_empty() && s[0] == b'0' {
s = &s[1..];
}
//if all zeros are consumed and no other numbers are left then the number is 0
if s.is_empty() {
return Ok(Bigint{sign:1, digits: vec![0]});
}
let mut digits = Vec::<u8>::new();
for &c in s {
match (c as char).to_digit(10) {
Some(digit) => digits.push(digit as u8),
None => return Err(ParseError)
};
}
if digits.len() == 1 && digits[0] == 0 {
sign = 1;
}
Ok(Bigint{
sign: sign,
digits: digits
})
}
}
}
use std::cmp::Ordering;
impl PartialOrd for Bigint {
fn partial_cmp(&self, other: &Bigint) -> Option<Ordering> {
//use cmp from Ord
Some(self.cmp(other))
}
}
impl Ord for Bigint {
fn cmp(&self, other: &Bigint) -> Ordering {
//first compare by sign
match self.sign.cmp(&other.sign){
Ordering::Equal => {
//then compare by number of digits
//if numbers are positive then compare as normal
if self.sign == 1 {
match self.digits.len().cmp(&other.digits.len()) {
Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
order => order
}
}
//if numbers are negative then compare in reverse
else{
match self.digits.len().cmp(&other.digits.len()) {
Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
Ordering::Greater => Ordering::Less,
Ordering::Less => Ordering::Greater
}
}
},
order => order
}
}
}
impl PartialEq for Bigint {
fn eq(&self, other: &Bigint) -> bool{
match self.cmp(other) {
Ordering::Equal => true,
_ => false
}
}
}
use std::ops::{Add, Sub, Neg};
impl Add for Bigint {
type Output = Bigint;
fn add(self, other: Self) -> Self {
let (new_sign, mut new_digits) = match self.sign == other.sign {
true => ( self.sign.clone(), Bigint::add_digits(self.digits, other.digits)),
false =>{
let compare = match self.digits.len().cmp(&other.digits.len()) {
Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
order => order
};
match (self.sign > other.sign, compare) {
(true, Ordering::Greater) => ( 1, Bigint::subtract_digits(self.digits, other.digits)),
(true, Ordering::Less) => ( -1, Bigint::subtract_digits(other.digits, self.digits)),
(true, Ordering::Equal) => ( 1, vec![0] ),
(false, Ordering::Greater) => ( -1, Bigint::subtract_digits(self.digits, other.digits)),
(false, Ordering::Less) => ( 1, Bigint::subtract_digits(other.digits, self.digits)),
(false, Ordering::Equal) => ( 1, vec![0] )
}
}
};
if new_digits[0] == 0 { new_digits = vec![0]; };
Bigint::from_components(new_sign, new_digits)
}
}
impl Sub for Bigint {
type Output = Bigint;
fn sub(self, other: Self) -> Self {
self.add(other.neg())
}
}
impl Neg for Bigint {
type Output = Bigint;
fn neg(self) -> Self {
Bigint{sign: -self.sign, digits: self.digits.clone()}
}
}
#[cfg(test)]
mod tests {
use crate::Bigint;
use std::{ str::FromStr };
use crate::ParseError;
use std::cmp::Ordering;
#[test]
fn initializing() {
assert_eq!(Bigint::new(), Bigint{sign:1, digits: vec![0]});
assert_eq!( Bigint::from_str("123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("0").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("+123").unwrap(),
Bigint{sign: 1, digits:vec![1,2,3]});
assert_eq!( Bigint::from_str("-123").unwrap(),
Bigint{sign: -1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("000123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("000123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("+0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("-0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("-000123").unwrap(),
Bigint{sign: -1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("asd"), Err(ParseError));
}
#[test]
fn sign_check() {
assert_eq!(Bigint::from_str("123").unwrap().is_positive(), true);
assert_eq!(Bigint::from_str("+984").unwrap().is_positive(), true);
assert_eq!(Bigint::from_str("0").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("+0").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("-123").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("-456").unwrap().is_negative(), true);
assert_eq!(Bigint::from_str("0").unwrap().is_negative(), false);
assert_eq!(Bigint::from_str("-0").unwrap().is_negative(), false);
}
#[test]
fn comparing() {
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("12").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("12").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-13").unwrap().cmp(&Bigint::from_str("-123").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-123").unwrap().cmp(&Bigint::from_str("-123").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-12").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("-12").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-0").unwrap().cmp(&Bigint::from_str("-0").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-0").unwrap().cmp(&Bigint::from_str("+0").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-1234").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("-12").unwrap()), Ordering::Greater);
}
#[test]
fn add() {
let mut a = Bigint::from_str("11111").unwrap();
let mut b = Bigint::from_str("111").unwrap();
assert_eq!(a + b, Bigint::from_str("11222").unwrap());
a = Bigint::from_str("123").unwrap();
b = Bigint::from_str("-123").unwrap();
assert_eq!( a + b, Bigint::from_str("0").unwrap());
a = Bigint::from_str("-123").unwrap();
b = Bigint::from_str("-123").unwrap();
assert_eq!( a + b, Bigint::from_str("-246").unwrap());
a = Bigint::from_str("100").unwrap();
b = Bigint::from_str("-5").unwrap();
assert_eq!( a + b, Bigint::from_str("95").unwrap());
a = Bigint::from_str("-10").unwrap();
b = Bigint::from_str("5").unwrap();
assert_eq!( a + b, Bigint::from_str("-5").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!( a + b, Bigint::from_str("0").unwrap());
}
#[test]
fn sub() {
let mut a = Bigint::from_str("11111").unwrap();
let mut b = Bigint::from_str("111").unwrap();
assert_eq!(a - b, Bigint::from_str("11000").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("15").unwrap();
assert_eq!(a - b, Bigint::from_str("-5").unwrap());
a = Bigint::from_str("15").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("5").unwrap());
a = Bigint::from_str("-10").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("-20").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("-10").unwrap();
assert_eq!(a - b, Bigint::from_str("10").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!(a - b, Bigint::from_str("10").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!(a - b, Bigint::from_str("0").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("0").unwrap());
}
#[test]
fn big_numbers_test() {
let a = Bigint::from_str("421312412315163584769").unwrap();
let b = Bigint::from_str("37153268356257273685").unwrap();
assert_eq!( a + b, Bigint::from_str("458465680671420858454").unwrap());
let a = Bigint::from_str("421312412315163584769").unwrap();
let b = Bigint::from_str("37153268356257273685").unwrap();
assert_eq!( a - b, Bigint::from_str("384159143958906311084").unwrap());
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20201127-2274206-10dgovw/solution)
    Finished test [unoptimized + debuginfo] target(s) in 1.60s
     Running target/debug/deps/solution_test-589a43f0f4b10ca3

running 15 tests
test solution_test::test_bigint_construction ... ok
test solution_test::test_bigint_nonzero_sign ... ok
test solution_test::test_bigint_zero_sign ... ok
test solution_test::test_comparison ... FAILED
test solution_test::test_invalid_string ... ok
test solution_test::test_neutralization ... ok
test solution_test::test_parsing_with_and_without_sign ... ok
test solution_test::test_parsing_with_leading_zeroes ... ok
test solution_test::test_sub_1_basic ... ok
test solution_test::test_sub_2_diferent_lengths ... ok
test solution_test::test_sub_3_carry ... ok
test solution_test::test_sum_1_basic ... ok
test solution_test::test_sum_2_different_lengths ... ok
test solution_test::test_sum_3_overflow ... FAILED
test solution_test::test_sum_4_negative ... ok

failures:

---- solution_test::test_comparison stdout ----
thread 'main' panicked at 'assertion failed: bigint("-1") > bigint("-2")', tests/solution_test.rs:171:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- solution_test::test_sum_3_overflow stdout ----
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `Bigint { sign: 1, digits: [1, 9, 9, 0] }`,
 right: `Bigint { sign: 1, digits: [1, 0, 0, 0] }`', tests/solution_test.rs:97:5


failures:
    solution_test::test_comparison
    solution_test::test_sum_3_overflow

test result: FAILED. 13 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test solution_test'

История (4 версии и 1 коментар)

Ивайло качи първо решение на 26.11.2020 18:11 (преди 8 месеца)

Ивайло качи решение на 27.11.2020 12:38 (преди 8 месеца)

use std::{str::FromStr, vec};
#[derive(Debug, Eq)]
pub struct Bigint {
sign: i8,
digits: Vec<u8>,
}
impl Bigint {
pub fn new() -> Self {
Bigint::from_components(1, vec![0])
}
fn from_components(sign: i8, digits: Vec<u8>) -> Self {
Bigint{
sign: sign,
digits: digits
}
}
/// Връща `true` ако числото е положително. Нулата не е положителна.
pub fn is_positive(&self) -> bool {
if self.digits.len() == 1 && self.digits[0] == 0 {
false
}
else if self.sign == 1 {
true
}
else {
false
}
}
/// Връща `true` ако числото е отрицателно. Нулата не е отрицателна.
pub fn is_negative(&self) -> bool {
if self.digits.len() == 1 && self.digits[0] == 0 {
false
}
else if self.sign == -1 {
true
}
else {
false
}
}
fn add_digits(left: Vec<u8>, right: Vec<u8>) -> Vec<u8> {
let mut new_digits = Vec::<u8>::new();
let mut left_iter = left.iter().rev();
let mut right_iter = right.iter().rev();
let mut carry_over = 0;
loop {
match (left_iter.next(), right_iter.next()) {
(Some(x), Some(y)) => {
new_digits.push( (x + y) % 10 + carry_over );
carry_over = (x + y) / 10;
},
(Some(x), None) => new_digits.push( x.clone() ),
(None, Some(y)) => new_digits.push( y.clone() ),
(None, None) => break,
}
}
if carry_over == 1 {
new_digits.push(1);
}
new_digits.reverse();
new_digits
}
fn subtract_digits(larger: Vec<u8>, smaller: Vec<u8>) -> Vec<u8> {
let mut new_digits = Vec::<u8>::new();
let mut left_iter = larger.iter().rev();
let mut right_iter = smaller.iter().rev();
let mut carry_over = 0;
loop {
match (left_iter.next(), right_iter.next()) {
(Some(x), Some(y)) => {
let digit = (*x as i8) - (*y as i8) - (carry_over as i8);
if digit < 0 {
new_digits.push( (digit + 10) as u8 );
carry_over = 1;
}
else {
new_digits.push( digit as u8 );
carry_over = 0;
}
},
(Some(x), None) => {
let digit = (*x as i8) - (carry_over as i8);
if digit < 0 {
new_digits.push( (digit + 10) as u8 );
carry_over = 1;
}
else {
new_digits.push( digit as u8 );
carry_over = 0;
}
},
(None, Some(_)) => unreachable!(),
(None, None) => break,
}
}
new_digits.reverse();
if new_digits[0] == 0 {
let mut i = 0;
while new_digits[i] == 0 {
i += 1
}
new_digits.drain(0..i);
}
new_digits
}
}
#[derive(Debug, PartialEq)]
pub struct ParseError;
impl FromStr for Bigint {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.as_bytes();
if s.is_empty(){
return Ok(Bigint::from_components(1, vec![0]));
}
let (mut sign, mut s) = match s[0] {
b'+' => (1, &s[1..]),
b'-' => (-1, &s[1..]),
_ => (1, s)
};
if s.is_empty() {
return Err(ParseError);
}
else if s.len() == 1 && s[0] == 48{
Ok(Bigint{
sign: 1,
digits: vec![0]
})
}
else {
//consume zeros infront of number
while !s.is_empty() && s[0] == b'0' {
s = &s[1..];
}
//if all zeros are consumed and no other numbers are left then the number is 0
if s.is_empty() {
return Ok(Bigint{sign:1, digits: vec![0]});
}
let mut digits = Vec::<u8>::new();
for &c in s {
match (c as char).to_digit(10) {
Some(digit) => digits.push(digit as u8),
None => return Err(ParseError)
};
}
if digits.len() == 1 && digits[0] == 0 {
sign = 1;
}
Ok(Bigint{
sign: sign,
digits: digits
})
}
}
}
use std::cmp::Ordering;
impl PartialOrd for Bigint {
fn partial_cmp(&self, other: &Bigint) -> Option<Ordering> {
//use cmp from Ord
Some(self.cmp(other))
}
}
impl Ord for Bigint {
fn cmp(&self, other: &Bigint) -> Ordering {
//first compare by sign
match self.sign.cmp(&other.sign){
Ordering::Equal => {
//then compare by number of digits
match self.digits.len().cmp(&other.digits.len()) {
Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
order => order
}
},
order => order
}
}
}
impl PartialEq for Bigint {
fn eq(&self, other: &Bigint) -> bool{
match self.cmp(other) {
Ordering::Equal => true,
_ => false
}
}
}
use std::ops::{Add, Sub, Neg};
impl Add for Bigint {
type Output = Bigint;
fn add(self, other: Self) -> Self {
let (new_sign, mut new_digits) = match self.sign == other.sign {
true => ( self.sign.clone(), Bigint::add_digits(self.digits, other.digits)),
false =>{
let compare = match self.digits.len().cmp(&other.digits.len()) {
Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
order => order
};
match (self.sign > other.sign, compare) {
(true, Ordering::Greater) => ( 1, Bigint::subtract_digits(self.digits, other.digits)),
(true, Ordering::Less) => ( -1, Bigint::subtract_digits(other.digits, self.digits)),
(true, Ordering::Equal) => ( 1, vec![0] ),
(false, Ordering::Greater) => ( -1, Bigint::subtract_digits(self.digits, other.digits)),
(false, Ordering::Less) => ( 1, Bigint::subtract_digits(other.digits, self.digits)),
(false, Ordering::Equal) => ( 1, vec![0] )
}
}
};
if new_digits[0] == 0 { new_digits = vec![0]; };
Bigint::from_components(new_sign, new_digits)
}
}
impl Sub for Bigint {
type Output = Bigint;
fn sub(self, other: Self) -> Self {
self.add(other.neg())
}
}
impl Neg for Bigint {
type Output = Bigint;
fn neg(self) -> Self {
Bigint{sign: -self.sign, digits: self.digits.clone()}
}
}
#[cfg(test)]
mod tests {
use crate::Bigint;
use std::{ str::FromStr };
use crate::ParseError;
use std::cmp::Ordering;
#[test]
fn initializing() {
assert_eq!(Bigint::new(), Bigint{sign:1, digits: vec![0]});
assert_eq!( Bigint::from_str("123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("0").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("+123").unwrap(),
Bigint{sign: 1, digits:vec![1,2,3]});
assert_eq!( Bigint::from_str("-123").unwrap(),
Bigint{sign: -1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("000123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("000123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("+0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("-0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("-000123").unwrap(),
Bigint{sign: -1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("asd"), Err(ParseError));
}
#[test]
fn sign_check() {
assert_eq!(Bigint::from_str("123").unwrap().is_positive(), true);
assert_eq!(Bigint::from_str("+984").unwrap().is_positive(), true);
assert_eq!(Bigint::from_str("0").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("+0").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("-123").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("-456").unwrap().is_negative(), true);
assert_eq!(Bigint::from_str("0").unwrap().is_negative(), false);
assert_eq!(Bigint::from_str("-0").unwrap().is_negative(), false);
}
#[test]
fn comparing() {
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("12").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("12").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-123").unwrap().cmp(&Bigint::from_str("-123").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-12").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("-12").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-0").unwrap().cmp(&Bigint::from_str("-0").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-0").unwrap().cmp(&Bigint::from_str("+0").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-1234").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("-12").unwrap()), Ordering::Greater);
}
#[test]
fn add() {
let mut a = Bigint::from_str("11111").unwrap();
let mut b = Bigint::from_str("111").unwrap();
assert_eq!(a + b, Bigint::from_str("11222").unwrap());
a = Bigint::from_str("123").unwrap();
b = Bigint::from_str("-123").unwrap();
assert_eq!( a + b, Bigint::from_str("0").unwrap());
a = Bigint::from_str("-123").unwrap();
b = Bigint::from_str("-123").unwrap();
assert_eq!( a + b, Bigint::from_str("-246").unwrap());
a = Bigint::from_str("100").unwrap();
b = Bigint::from_str("-5").unwrap();
assert_eq!( a + b, Bigint::from_str("95").unwrap());
a = Bigint::from_str("-10").unwrap();
b = Bigint::from_str("5").unwrap();
assert_eq!( a + b, Bigint::from_str("-5").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!( a + b, Bigint::from_str("0").unwrap());
}
#[test]
fn sub() {
let mut a = Bigint::from_str("11111").unwrap();
let mut b = Bigint::from_str("111").unwrap();
assert_eq!(a - b, Bigint::from_str("11000").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("15").unwrap();
assert_eq!(a - b, Bigint::from_str("-5").unwrap());
a = Bigint::from_str("15").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("5").unwrap());
a = Bigint::from_str("-10").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("-20").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("-10").unwrap();
assert_eq!(a - b, Bigint::from_str("10").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!(a - b, Bigint::from_str("10").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!(a - b, Bigint::from_str("0").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("0").unwrap());
}
+ #[test]
+ fn big_numbers_test() {
+
+ let a = Bigint::from_str("421312412315163584769").unwrap();
+ let b = Bigint::from_str("37153268356257273685").unwrap();
+ assert_eq!( a + b, Bigint::from_str("458465680671420858454").unwrap());
+
+ let a = Bigint::from_str("421312412315163584769").unwrap();
+ let b = Bigint::from_str("37153268356257273685").unwrap();
+ assert_eq!( a - b, Bigint::from_str("384159143958906311084").unwrap());
+
+ }
}

Ивайло качи решение на 27.11.2020 12:42 (преди 8 месеца)

use std::{str::FromStr, vec};
#[derive(Debug, Eq)]
pub struct Bigint {
sign: i8,
digits: Vec<u8>,
}
impl Bigint {
pub fn new() -> Self {
Bigint::from_components(1, vec![0])
}
fn from_components(sign: i8, digits: Vec<u8>) -> Self {
Bigint{
sign: sign,
digits: digits
}
}
/// Връща `true` ако числото е положително. Нулата не е положителна.
pub fn is_positive(&self) -> bool {
if self.digits.len() == 1 && self.digits[0] == 0 {
false
}
else if self.sign == 1 {
true
}
else {
false
}
}
/// Връща `true` ако числото е отрицателно. Нулата не е отрицателна.
pub fn is_negative(&self) -> bool {
if self.digits.len() == 1 && self.digits[0] == 0 {
false
}
else if self.sign == -1 {
true
}
else {
false
}
}
fn add_digits(left: Vec<u8>, right: Vec<u8>) -> Vec<u8> {
let mut new_digits = Vec::<u8>::new();
let mut left_iter = left.iter().rev();
let mut right_iter = right.iter().rev();
let mut carry_over = 0;
loop {
match (left_iter.next(), right_iter.next()) {
(Some(x), Some(y)) => {
new_digits.push( (x + y) % 10 + carry_over );
carry_over = (x + y) / 10;
},
(Some(x), None) => new_digits.push( x.clone() ),
(None, Some(y)) => new_digits.push( y.clone() ),
(None, None) => break,
}
}
if carry_over == 1 {
new_digits.push(1);
}
new_digits.reverse();
new_digits
}
fn subtract_digits(larger: Vec<u8>, smaller: Vec<u8>) -> Vec<u8> {
let mut new_digits = Vec::<u8>::new();
let mut left_iter = larger.iter().rev();
let mut right_iter = smaller.iter().rev();
let mut carry_over = 0;
loop {
match (left_iter.next(), right_iter.next()) {
(Some(x), Some(y)) => {
let digit = (*x as i8) - (*y as i8) - (carry_over as i8);
if digit < 0 {
new_digits.push( (digit + 10) as u8 );
carry_over = 1;
}
else {
new_digits.push( digit as u8 );
carry_over = 0;
}
},
(Some(x), None) => {
let digit = (*x as i8) - (carry_over as i8);
if digit < 0 {
new_digits.push( (digit + 10) as u8 );
carry_over = 1;
}
else {
new_digits.push( digit as u8 );
carry_over = 0;
}
},
(None, Some(_)) => unreachable!(),
(None, None) => break,
}
}
new_digits.reverse();
if new_digits[0] == 0 {
let mut i = 0;
while new_digits[i] == 0 {
i += 1
}
new_digits.drain(0..i);
}
new_digits
}
}
#[derive(Debug, PartialEq)]
pub struct ParseError;
impl FromStr for Bigint {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.as_bytes();
if s.is_empty(){
return Ok(Bigint::from_components(1, vec![0]));
}
let (mut sign, mut s) = match s[0] {
b'+' => (1, &s[1..]),
b'-' => (-1, &s[1..]),
_ => (1, s)
};
if s.is_empty() {
return Err(ParseError);
}
else if s.len() == 1 && s[0] == 48{
Ok(Bigint{
sign: 1,
digits: vec![0]
})
}
else {
//consume zeros infront of number
while !s.is_empty() && s[0] == b'0' {
s = &s[1..];
}
//if all zeros are consumed and no other numbers are left then the number is 0
if s.is_empty() {
return Ok(Bigint{sign:1, digits: vec![0]});
}
let mut digits = Vec::<u8>::new();
for &c in s {
match (c as char).to_digit(10) {
Some(digit) => digits.push(digit as u8),
None => return Err(ParseError)
};
}
if digits.len() == 1 && digits[0] == 0 {
sign = 1;
}
Ok(Bigint{
sign: sign,
digits: digits
})
}
}
}
use std::cmp::Ordering;
impl PartialOrd for Bigint {
fn partial_cmp(&self, other: &Bigint) -> Option<Ordering> {
//use cmp from Ord
Some(self.cmp(other))
}
}
impl Ord for Bigint {
fn cmp(&self, other: &Bigint) -> Ordering {
//first compare by sign
match self.sign.cmp(&other.sign){
Ordering::Equal => {
- //then compare by number of digits
- match self.digits.len().cmp(&other.digits.len()) {
- Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
- order => order
+ if self.sign == 1 {
+ //then compare by number of digits
+ match self.digits.len().cmp(&other.digits.len()) {
+ Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
+ order => order
+ }
}
+ else{
+ match self.digits.len().cmp(&other.digits.len()) {
+ Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
+ Ordering::Greater => Ordering::Less,
+ Ordering::Less => Ordering::Greater
+ }
+ }
},
order => order
}
}
}
impl PartialEq for Bigint {
fn eq(&self, other: &Bigint) -> bool{
match self.cmp(other) {
Ordering::Equal => true,
_ => false
}
}
}
use std::ops::{Add, Sub, Neg};
impl Add for Bigint {
type Output = Bigint;
fn add(self, other: Self) -> Self {
let (new_sign, mut new_digits) = match self.sign == other.sign {
true => ( self.sign.clone(), Bigint::add_digits(self.digits, other.digits)),
false =>{
let compare = match self.digits.len().cmp(&other.digits.len()) {
Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
order => order
};
match (self.sign > other.sign, compare) {
(true, Ordering::Greater) => ( 1, Bigint::subtract_digits(self.digits, other.digits)),
(true, Ordering::Less) => ( -1, Bigint::subtract_digits(other.digits, self.digits)),
(true, Ordering::Equal) => ( 1, vec![0] ),
(false, Ordering::Greater) => ( -1, Bigint::subtract_digits(self.digits, other.digits)),
(false, Ordering::Less) => ( 1, Bigint::subtract_digits(other.digits, self.digits)),
(false, Ordering::Equal) => ( 1, vec![0] )
}
}
};
if new_digits[0] == 0 { new_digits = vec![0]; };
Bigint::from_components(new_sign, new_digits)
}
}
impl Sub for Bigint {
type Output = Bigint;
fn sub(self, other: Self) -> Self {
self.add(other.neg())
}
}
impl Neg for Bigint {
type Output = Bigint;
fn neg(self) -> Self {
Bigint{sign: -self.sign, digits: self.digits.clone()}
}
}
#[cfg(test)]
mod tests {
use crate::Bigint;
use std::{ str::FromStr };
use crate::ParseError;
use std::cmp::Ordering;
#[test]
fn initializing() {
assert_eq!(Bigint::new(), Bigint{sign:1, digits: vec![0]});
assert_eq!( Bigint::from_str("123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("0").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("+123").unwrap(),
Bigint{sign: 1, digits:vec![1,2,3]});
assert_eq!( Bigint::from_str("-123").unwrap(),
Bigint{sign: -1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("000123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("000123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("+0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("-0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("-000123").unwrap(),
Bigint{sign: -1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("asd"), Err(ParseError));
}
#[test]
fn sign_check() {
assert_eq!(Bigint::from_str("123").unwrap().is_positive(), true);
assert_eq!(Bigint::from_str("+984").unwrap().is_positive(), true);
assert_eq!(Bigint::from_str("0").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("+0").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("-123").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("-456").unwrap().is_negative(), true);
assert_eq!(Bigint::from_str("0").unwrap().is_negative(), false);
assert_eq!(Bigint::from_str("-0").unwrap().is_negative(), false);
}
#[test]
fn comparing() {
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("12").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("12").unwrap()), Ordering::Greater);
+ assert_eq!(Bigint::from_str("-13").unwrap().cmp(&Bigint::from_str("-123").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-123").unwrap().cmp(&Bigint::from_str("-123").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-12").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("-12").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-0").unwrap().cmp(&Bigint::from_str("-0").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-0").unwrap().cmp(&Bigint::from_str("+0").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-1234").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("-12").unwrap()), Ordering::Greater);
}
#[test]
fn add() {
let mut a = Bigint::from_str("11111").unwrap();
let mut b = Bigint::from_str("111").unwrap();
assert_eq!(a + b, Bigint::from_str("11222").unwrap());
a = Bigint::from_str("123").unwrap();
b = Bigint::from_str("-123").unwrap();
assert_eq!( a + b, Bigint::from_str("0").unwrap());
a = Bigint::from_str("-123").unwrap();
b = Bigint::from_str("-123").unwrap();
assert_eq!( a + b, Bigint::from_str("-246").unwrap());
a = Bigint::from_str("100").unwrap();
b = Bigint::from_str("-5").unwrap();
assert_eq!( a + b, Bigint::from_str("95").unwrap());
a = Bigint::from_str("-10").unwrap();
b = Bigint::from_str("5").unwrap();
assert_eq!( a + b, Bigint::from_str("-5").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!( a + b, Bigint::from_str("0").unwrap());
}
#[test]
fn sub() {
let mut a = Bigint::from_str("11111").unwrap();
let mut b = Bigint::from_str("111").unwrap();
assert_eq!(a - b, Bigint::from_str("11000").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("15").unwrap();
assert_eq!(a - b, Bigint::from_str("-5").unwrap());
a = Bigint::from_str("15").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("5").unwrap());
a = Bigint::from_str("-10").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("-20").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("-10").unwrap();
assert_eq!(a - b, Bigint::from_str("10").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!(a - b, Bigint::from_str("10").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!(a - b, Bigint::from_str("0").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("0").unwrap());
}
#[test]
fn big_numbers_test() {
let a = Bigint::from_str("421312412315163584769").unwrap();
let b = Bigint::from_str("37153268356257273685").unwrap();
assert_eq!( a + b, Bigint::from_str("458465680671420858454").unwrap());
let a = Bigint::from_str("421312412315163584769").unwrap();
let b = Bigint::from_str("37153268356257273685").unwrap();
assert_eq!( a - b, Bigint::from_str("384159143958906311084").unwrap());
}
}

Ивайло качи решение на 27.11.2020 12:51 (преди 8 месеца)

use std::{str::FromStr, vec};
#[derive(Debug, Eq)]
pub struct Bigint {
sign: i8,
digits: Vec<u8>,
}
impl Bigint {
pub fn new() -> Self {
Bigint::from_components(1, vec![0])
}
fn from_components(sign: i8, digits: Vec<u8>) -> Self {
Bigint{
sign: sign,
digits: digits
}
}
/// Връща `true` ако числото е положително. Нулата не е положителна.
pub fn is_positive(&self) -> bool {
if self.digits.len() == 1 && self.digits[0] == 0 {
false
}
else if self.sign == 1 {
true
}
else {
false
}
}
/// Връща `true` ако числото е отрицателно. Нулата не е отрицателна.
pub fn is_negative(&self) -> bool {
if self.digits.len() == 1 && self.digits[0] == 0 {
false
}
else if self.sign == -1 {
true
}
else {
false
}
}
fn add_digits(left: Vec<u8>, right: Vec<u8>) -> Vec<u8> {
let mut new_digits = Vec::<u8>::new();
let mut left_iter = left.iter().rev();
let mut right_iter = right.iter().rev();
let mut carry_over = 0;
loop {
match (left_iter.next(), right_iter.next()) {
(Some(x), Some(y)) => {
new_digits.push( (x + y) % 10 + carry_over );
carry_over = (x + y) / 10;
},
(Some(x), None) => new_digits.push( x.clone() ),
(None, Some(y)) => new_digits.push( y.clone() ),
(None, None) => break,
}
}
if carry_over == 1 {
new_digits.push(1);
}
new_digits.reverse();
new_digits
}
fn subtract_digits(larger: Vec<u8>, smaller: Vec<u8>) -> Vec<u8> {
let mut new_digits = Vec::<u8>::new();
let mut left_iter = larger.iter().rev();
let mut right_iter = smaller.iter().rev();
let mut carry_over = 0;
loop {
match (left_iter.next(), right_iter.next()) {
(Some(x), Some(y)) => {
let digit = (*x as i8) - (*y as i8) - (carry_over as i8);
if digit < 0 {
new_digits.push( (digit + 10) as u8 );
carry_over = 1;
}
else {
new_digits.push( digit as u8 );
carry_over = 0;
}
},
(Some(x), None) => {
let digit = (*x as i8) - (carry_over as i8);
if digit < 0 {
new_digits.push( (digit + 10) as u8 );
carry_over = 1;
}
else {
new_digits.push( digit as u8 );
carry_over = 0;
}
},
(None, Some(_)) => unreachable!(),
(None, None) => break,
}
}
new_digits.reverse();
if new_digits[0] == 0 {
let mut i = 0;
while new_digits[i] == 0 {
i += 1
}
new_digits.drain(0..i);
}
new_digits
}
}
#[derive(Debug, PartialEq)]
pub struct ParseError;
impl FromStr for Bigint {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.as_bytes();
if s.is_empty(){
return Ok(Bigint::from_components(1, vec![0]));
}
let (mut sign, mut s) = match s[0] {
b'+' => (1, &s[1..]),
b'-' => (-1, &s[1..]),
_ => (1, s)
};
if s.is_empty() {
return Err(ParseError);
}
else if s.len() == 1 && s[0] == 48{
Ok(Bigint{
sign: 1,
digits: vec![0]
})
}
else {
//consume zeros infront of number
while !s.is_empty() && s[0] == b'0' {
s = &s[1..];
}
//if all zeros are consumed and no other numbers are left then the number is 0
if s.is_empty() {
return Ok(Bigint{sign:1, digits: vec![0]});
}
let mut digits = Vec::<u8>::new();
for &c in s {
match (c as char).to_digit(10) {
Some(digit) => digits.push(digit as u8),
None => return Err(ParseError)
};
}
if digits.len() == 1 && digits[0] == 0 {
sign = 1;
}
Ok(Bigint{
sign: sign,
digits: digits
})
}
}
}
use std::cmp::Ordering;
impl PartialOrd for Bigint {
fn partial_cmp(&self, other: &Bigint) -> Option<Ordering> {
//use cmp from Ord
Some(self.cmp(other))
}
}
impl Ord for Bigint {
fn cmp(&self, other: &Bigint) -> Ordering {
//first compare by sign
match self.sign.cmp(&other.sign){
Ordering::Equal => {
- if self.sign == 1 {
- //then compare by number of digits
+ //then compare by number of digits
+ //if numbers are positive then compare as normal
+ if self.sign == 1 {
match self.digits.len().cmp(&other.digits.len()) {
Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
order => order
}
}
- else{
+ //if numbers are negative then compare in reverse
+ else{
match self.digits.len().cmp(&other.digits.len()) {
Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
Ordering::Greater => Ordering::Less,
Ordering::Less => Ordering::Greater
}
}
},
order => order
}
}
}
impl PartialEq for Bigint {
fn eq(&self, other: &Bigint) -> bool{
match self.cmp(other) {
Ordering::Equal => true,
_ => false
}
}
}
use std::ops::{Add, Sub, Neg};
impl Add for Bigint {
type Output = Bigint;
fn add(self, other: Self) -> Self {
let (new_sign, mut new_digits) = match self.sign == other.sign {
true => ( self.sign.clone(), Bigint::add_digits(self.digits, other.digits)),
false =>{
let compare = match self.digits.len().cmp(&other.digits.len()) {
Ordering::Equal => self.digits.cmp(&other.digits), //compare vectors of digits with cmp of vec
order => order
};
match (self.sign > other.sign, compare) {
(true, Ordering::Greater) => ( 1, Bigint::subtract_digits(self.digits, other.digits)),
(true, Ordering::Less) => ( -1, Bigint::subtract_digits(other.digits, self.digits)),
(true, Ordering::Equal) => ( 1, vec![0] ),
(false, Ordering::Greater) => ( -1, Bigint::subtract_digits(self.digits, other.digits)),
(false, Ordering::Less) => ( 1, Bigint::subtract_digits(other.digits, self.digits)),
(false, Ordering::Equal) => ( 1, vec![0] )
}
}
};
if new_digits[0] == 0 { new_digits = vec![0]; };
Bigint::from_components(new_sign, new_digits)
}
}
impl Sub for Bigint {
type Output = Bigint;
fn sub(self, other: Self) -> Self {
self.add(other.neg())
}
}
impl Neg for Bigint {
type Output = Bigint;
fn neg(self) -> Self {
Bigint{sign: -self.sign, digits: self.digits.clone()}
}
}
#[cfg(test)]
mod tests {
use crate::Bigint;
use std::{ str::FromStr };
use crate::ParseError;
use std::cmp::Ordering;
#[test]
fn initializing() {
assert_eq!(Bigint::new(), Bigint{sign:1, digits: vec![0]});
assert_eq!( Bigint::from_str("123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("0").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("+123").unwrap(),
Bigint{sign: 1, digits:vec![1,2,3]});
assert_eq!( Bigint::from_str("-123").unwrap(),
Bigint{sign: -1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("000123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("000123").unwrap(),
Bigint{sign: 1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("+0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("-0000").unwrap(),
Bigint{sign: 1, digits: vec![0]});
assert_eq!( Bigint::from_str("-000123").unwrap(),
Bigint{sign: -1, digits: vec![1,2,3]});
assert_eq!( Bigint::from_str("asd"), Err(ParseError));
}
#[test]
fn sign_check() {
assert_eq!(Bigint::from_str("123").unwrap().is_positive(), true);
assert_eq!(Bigint::from_str("+984").unwrap().is_positive(), true);
assert_eq!(Bigint::from_str("0").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("+0").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("-123").unwrap().is_positive(), false);
assert_eq!(Bigint::from_str("-456").unwrap().is_negative(), true);
assert_eq!(Bigint::from_str("0").unwrap().is_negative(), false);
assert_eq!(Bigint::from_str("-0").unwrap().is_negative(), false);
}
#[test]
fn comparing() {
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("12").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("12").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-13").unwrap().cmp(&Bigint::from_str("-123").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-123").unwrap().cmp(&Bigint::from_str("-123").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-12").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("-12").unwrap()), Ordering::Greater);
assert_eq!(Bigint::from_str("-0").unwrap().cmp(&Bigint::from_str("-0").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-0").unwrap().cmp(&Bigint::from_str("+0").unwrap()), Ordering::Equal);
assert_eq!(Bigint::from_str("-1234").unwrap().cmp(&Bigint::from_str("123").unwrap()), Ordering::Less);
assert_eq!(Bigint::from_str("123").unwrap().cmp(&Bigint::from_str("-12").unwrap()), Ordering::Greater);
}
#[test]
fn add() {
let mut a = Bigint::from_str("11111").unwrap();
let mut b = Bigint::from_str("111").unwrap();
assert_eq!(a + b, Bigint::from_str("11222").unwrap());
a = Bigint::from_str("123").unwrap();
b = Bigint::from_str("-123").unwrap();
assert_eq!( a + b, Bigint::from_str("0").unwrap());
a = Bigint::from_str("-123").unwrap();
b = Bigint::from_str("-123").unwrap();
assert_eq!( a + b, Bigint::from_str("-246").unwrap());
a = Bigint::from_str("100").unwrap();
b = Bigint::from_str("-5").unwrap();
assert_eq!( a + b, Bigint::from_str("95").unwrap());
a = Bigint::from_str("-10").unwrap();
b = Bigint::from_str("5").unwrap();
assert_eq!( a + b, Bigint::from_str("-5").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!( a + b, Bigint::from_str("0").unwrap());
}
#[test]
fn sub() {
let mut a = Bigint::from_str("11111").unwrap();
let mut b = Bigint::from_str("111").unwrap();
assert_eq!(a - b, Bigint::from_str("11000").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("15").unwrap();
assert_eq!(a - b, Bigint::from_str("-5").unwrap());
a = Bigint::from_str("15").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("5").unwrap());
a = Bigint::from_str("-10").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("-20").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("-10").unwrap();
assert_eq!(a - b, Bigint::from_str("10").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!(a - b, Bigint::from_str("10").unwrap());
a = Bigint::from_str("0").unwrap();
b = Bigint::from_str("0").unwrap();
assert_eq!(a - b, Bigint::from_str("0").unwrap());
a = Bigint::from_str("10").unwrap();
b = Bigint::from_str("10").unwrap();
assert_eq!(a - b, Bigint::from_str("0").unwrap());
}
#[test]
fn big_numbers_test() {
let a = Bigint::from_str("421312412315163584769").unwrap();
let b = Bigint::from_str("37153268356257273685").unwrap();
assert_eq!( a + b, Bigint::from_str("458465680671420858454").unwrap());
let a = Bigint::from_str("421312412315163584769").unwrap();
let b = Bigint::from_str("37153268356257273685").unwrap();
assert_eq!( a - b, Bigint::from_str("384159143958906311084").unwrap());
}
}

Имаш тестове, но си изпуснал доста интересни случаи -- невалидни низове с различни форми, включително не-utf8, сравнение на числа с еднакъв брой цифри (мисля че имаш само едно, което е равенство, само един случай), събиране с overflow мисля че ти липсва. Хвърли едно око на пълния тест за идеи.