0

I am building a program on solidity that receives 3 values(bonus, value1, value2) through function, Then, another value called priority is calculated as follows: Priority= (0.5*Value1 + 0.5*value2) / bonus. However, when I code this function in remix, I got errors. Is there any way to fix this and I still can compute the "Priority" on solidity?

pragma solidity ^0.4.24; 
contract Test{

struct student{
uint bonus;
uint value1;
uint value2;
uint Priority;  //priority of student
 }


mapping(address => student) students ; //etherum does not allow 
declaration of a function of type mapping so we define array of addresses
address [] public student_list;  // array of all student addresses

function Recieve_Request(address _address,uint _bonus, uint _value1, uint 
_value2) public {          

var student = students[_address]; //instance of struct student and map it to 
 students mapping
student.bonus=_bonus;
student.value1=_value1;
student.value2=_value2;
student.Priority=(0.5 * _value1 + 0.5 * _value2)/ _bonus;  

 student_list.push(_address) -1;
     }


      function get_ESU(address ins) view public returns (uint, uint, uint) {
    return (students[ins].value1, students[ins].value2, 
  students[ins].Priority);
}

}
  • what kind of issues do you have? – Aquila Oct 3 '18 at 17:05
1

The problem is simply that ‘0.5’ do not exist in integer math. The minimum positive number is ‘1’.

You can divide by 2 instead of multiplying by 0.5.

0

Here's an explained code example that should get you on the right track.

pragma solidity ^0.4.24; 

contract Test {

    // storage is packed based on how much data we actually want to store,
    // to minimise the storage costs, we're going to use expected uint types
    struct StudentType {
        uint8 bonus;        // 0 - 255
        uint16 value1;      // 0 - 65535
        uint16 value2;      // 0 - 65535
        uint16 Priority;    // 0 - 65535
    }

    mapping (address => StudentType) public studentsByAddress; 
    mapping (uint256 => address) public studentsByInsertId; 
    uint256 public studentCount = 0;

    function saveNewRecord(address _address, uint8 _bonus, uint16 _value1, uint16 _value2) public {          

        // instance of struct student and map it to students mapping;
        StudentType storage student = studentsByAddress[_address]; 
        student.bonus = _bonus;
        student.value1 = _value1;
        student.value2 = _value2;

        student.Priority = this.calculatePriority( _value1, _value2, _bonus);

        // map address to current insert id
        // ++uint makes our index start at 1 since the incrementation happens before 
        // if you want it to start at 0, then do uint++
        studentsByInsertId[studentCount++] = _address;

    }

    /*
        solidity does not support floating point math, so we can't really use "decimals"
        and to go around this, we multiply everything we need by 100, and divide the result by 100
        keep in mind division also floors the result ( in case the result 0 to 0,999(9) it will be 0 )

        depending on the precision you actually want the more "zeroes" you're going to use. 
    */

    function calculatePriority(uint16 _value1, uint16 _value2, uint8 _bonus) pure public returns ( uint16 ) {
        // store the calculation in a big enough value
        uint256 result = ( ( ( 50 * _value1 ) + ( 50 * _value2 ) ) / _bonus ) / 100;

        // convert result
        return uint16( result );
    }

    /*
        not really needed since you can use the "studentsByAddress" mapping method created by solidity
        unless you want to "hide" or manipulate some data
    */
    function get_ESU(address ins) view public returns (uint, uint, uint) {
        return (
            studentsByAddress[ins].value1,
            studentsByAddress[ins].value2,
            studentsByAddress[ins].Priority
        );
    }

}

You should also be looking at using the OpenZeppelin SafeMath library when dealing with arithmetic operations, as it will save you a lot of headaches in the future.

  • what if _value1 and _value2 can be only a value from 0 to 1. and not an integer. How can we handle this situation? – Mohamed Oct 4 '18 at 1:33
  • then send them to the contract as value x 100 and keep the priority in contract between 0 and 100, and in the frontend divide by 100 to have the value you wanted. – Micky Socaci Oct 4 '18 at 1:44
  • I tried to deploy your contract and I passed the following values to saveNewRecord("any address", 100,10,10). but the function returns me 0 as the priority which is not the value I want to have – Mohamed Oct 4 '18 at 2:09
  • 100, 10, 10 should return 0.1 .. since solidity does not support decimals, it will floor the value, resulting in 0. the only thing you can do is, multiply the priority by 100 and keep it that way in the contract, as i said earlier You can of course create a custom floating point data type using assembly and store and access your data using that approach. en.wikipedia.org/wiki/Single-precision_floating-point_format – Micky Socaci Oct 4 '18 at 2:58
  • Last question. If the contract received 10 records of students with each one has a priority stored in the mapping. Can you write a function that sorts them from highest to lowest priority ?? – Mohamed Oct 4 '18 at 3:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.