No puedo hacer ninguna división entera

Estoy construyendo un nuevo contrato inteligente pero realmente no puedo entender cómo realizar la división de enteros. Sé que los números de punto fijo aún no se han implementado, pero debería ser posible realizar 100/3 = 33, al menos.

Espero que alguien pueda ayudarme. He visto varios ejemplos en los que hablan de la división de enteros redondeados, pero parece que no pueden realizarla.

Saludos, Hugo

Solo para mostrar el mensaje de error: ballot.sol:3:19: Error: Type rational_const 5/4 is not implicitly convertible to expected type uint256. Try converting to type ufixed8x8 or use an explicit conversion. uint result = 5/4entiendo que la conversión no es implícitamente posible, pero tampoco lo es explícito y no veo nada que pueda hacer para lograr la división de enteros
¿Podría publicar su código y la versión de solidez que está usando?

Respuestas (4)

El problema es que 4 y 5 caben en menos de 256 bits (cada uno). Terminas con pequeños uints en la expresión constante, y luego esos no se convierten fácilmente a uint256, así que... lanza el tipo explícitamente.

uint x = uint(4)/uint(5);

La moraleja es precaución con las constantes porque se pueden convertir en tipos inesperados.

Una idea esquemática:

contract Divide {
    
    function getDivided(uint numerator, uint denominator) public constant returns(uint quotient, uint remainder) {
        quotient  = numerator / denominator;
        remainder = numerator - denominator * quotient;
    }
}

Consulte también "SafeMath" con "safeDiv()" en Zeppelin: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol

Además, dado que 4/5 obviamente da como resultado 0 resto 4, ¿posiblemente realmente esté apuntando a algo más como el 80%?

Puede aumentar la precisión trabajando con "decimal", como es común en los mercados financieros. Pasas pares, los dígitos y el desplazamiento decimal.

Entonces, 1.234 se escribiría como [1234, 3] con el 3 indicando que hay un decimal en el tercer lugar.

En este caso, calcularías 80, con 2 decimales (es decir, 0,80).

4 * 10 ** 2 = 400, 400/5 = 80 , elevamos 4 por 10 ^ 2 , así que devuelve... 80,2 y opcionalmente, un resto.

Espero eso ayude.

Wow Rob, muchas gracias por tu ayuda, ¡nos sentimos completamente perdidos en esto!
En mis pruebas, fue suficiente usar solo uint x = uint(4)/5;. Parece que el denominador no necesita un molde si el denominador es del mismo tipo y obtiene un molde.
En la práctica, suele ser suficiente saber que se produce truncamiento, no redondeo, y que existe polvo. 4/5 = 0. ` function foo() public pure return(uint x) { x = uint(4)/5; } `

como complemento a la respuesta de @rob puedes usar:

 function calcul(uint a, uint b, uint precision) view returns ( uint) {

     return a*(10**precision)/b;
 }

Si dividimos usando la función anterior 7/3 con una precisión de 5, generará 233333, lo que significa 7/3 = 2.33333. La conversión a flotante se puede hacer en el front-end.

Las expresiones literales tienen una precisión arbitraria hasta que se convierten (por ejemplo, se convierten) en un tipo no literal.

En este ejemplo, la expresión literal 5/4es un tipo de constante racional interna con precisión ilimitada y no puede reducirse implícitamente a uint256. Aparentemente, esta es una restricción a los racionales impuesta por el compilador.

Tenga en cuenta que para las expresiones literales de números enteros, el tipo resultante es el más pequeño que contendrá el valor de la expresión.

Ver también:

http://solidity.readthedocs.io/en/develop/types.html#rational-literals https://ethereumbuilders.gitbooks.io/guide/content/en/solidity_features.html

Puede usar una biblioteca matemática de punto fijo como ABDK Math 64.64 . Tiene un método divique divide un entero por otro y devuelve el resultado como un número binario de punto fijo con 64 dígitos binarios después del punto.