user76333
user76333

Reputation: 215

Difference in division results of big integers between Rust and Go

I've encountered an interesting issue while working with large integers in Rust and Go. Specifically, the results of division operations differ between the two languages when dealing with negative dividends. Here is the code for both languages:

Rust

use num_bigint::BigInt;
use std::str::FromStr;

fn main() {
    let n = BigInt::from_str("-4068122527548036313624952687320999183219209139149389824425650628448701979991259532638609685663741905551578447595775644964695361846038949186131821248175179900695219937607954907860922507949244416").unwrap();
    let d = BigInt::from_str(
        "115792089237316195423570985008687907852837564279074904382605163141518161494337",
    )
    .unwrap();
    let res = &n / &d;
    println!("res:{}", result);
}

Go

package main

import "math/big"

func main() {
    var n, d, res big.Int
    n.SetString("-4068122527548036313624952687320999183219209139149389824425650628448701979991259532638609685663741905551578447595775644964695361846038949186131821248175179900695219937607954907860922507949244416", 10)
    d.SetString("115792089237316195423570985008687907852837564279074904382605163141518161494337", 10)
    res.Div(&n, &d)
    println("res:", res.String())
}

Output

Rust: -35132991850681684771865987637349505035135798334672277824131793024179346079627919418184483600280933255791109974931548

Go: -35132991850681684771865987637349505035135798334672277824131793024179346079627919418184483600280933255791109974931549

As you can see, Rust rounds the result towards zero, while Go rounds towards negative infinity. Can anyone explain why this difference exists and whether there is a way to align the behavior of these two languages in such division operations?

Upvotes: -5

Views: 116

Answers (1)

Richard Neumann
Richard Neumann

Reputation: 455

num_bigint appears to be using a different rounding strategy per default:

use num_bigint::BigInt;
use num_integer::Integer;
use num_traits::ops::euclid::Euclid;
use std::str::FromStr;

fn main() {
    let n = BigInt::from_str("-4068122527548036313624952687320999183219209139149389824425650628448701979991259532638609685663741905551578447595775644964695361846038949186131821248175179900695219937607954907860922507949244416").unwrap();
    let d = BigInt::from_str(
        "115792089237316195423570985008687907852837564279074904382605163141518161494337",
    )
    .unwrap();
    let rust = BigInt::from_str("-35132991850681684771865987637349505035135798334672277824131793024179346079627919418184483600280933255791109974931548").unwrap();
    let go = BigInt::from_str("-35132991850681684771865987637349505035135798334672277824131793024179346079627919418184483600280933255791109974931549").unwrap();
    let res = &n / &d;
    assert_eq!(res, rust);
    let res = n.div_floor(&d);
    assert_eq!(res, go);
    let res = n.div_euclid(&d);
    assert_eq!(res, go);
}

Upvotes: 3

Related Questions