logankilpatrick
logankilpatrick

Reputation: 14501

Why does division result in a non-rational number, when there should be a remainder, in solidity

I have the following solidity Contract:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.8.0;

contract AverageStream {

    uint private count;
    uint private pre_average;

    constructor() {
        count = 0;
        pre_average = 0;
    }
    
    function add_element(uint num) public {
        count += 1;
        pre_average += num;
    }
    
    function get_average() public view returns (uint) {
        return uint(pre_average) / uint(count);
    }
    
}

I then invoke it and use it in Python via:

Average_Stream.functions.add_element(5).transact()
Average_Stream.functions.add_element(2).transact()

Average_Stream.functions.get_average().call()

which outputs "3" where I would be expecting 3.5. I read a bunch of posts and tried all different variations of types for that function and such. What am I missing here? The docs here (https://docs.soliditylang.org/en/v0.7.6/types.html#rational-literals) say I should be getting a rational as the output post v0.4.0.

Upvotes: 0

Views: 561

Answers (1)

Petr Hejda
Petr Hejda

Reputation: 43481

Solidity is able to work with rationals to some extent. But you're returning an integer.

pragma solidity ^0.7.0;

contract Test {
   function divide() public pure returns (uint) {
        return uint(7) / uint(2); // 7/2 is 3.5, but returns uint(3.5) which is 3
   }
   
   function add() public pure returns (uint) {
        return 3.5 + 0.5; // returns 4
   }
}

There's currently no native decimal data type (to store or return decimal numbers).

However, most implementations use a predefined amount of decimals and use the amount of decimals as exponents of 10.

Example: 1 token with 2 decimals is usually stored as an integer with a value of 100. When you send someone 0,5 of the token, the stored amount is subtracted by 50.

Upvotes: 1

Related Questions