En mi dApp, el usuario establece la tarifa de entrada para el juego que está creando. La tarifa de entrada para los juegos suele oscilar entre $ 5 USD y $ 50 USD. ¿Qué unidad debo usar para el método de contrato que acepta el pago del juego (es decir, el tipo para introducir el parámetro de método relevante)? ¿Debo usar: wei, gwei, eth, etc.?
Además, ¿qué tipo de solidez debo usar internamente en mi contrato que haga una buena cantidad de cálculos numéricos cuando llegue el momento de pagar a los jugadores? ¿Supongo que un tipo de punto fijo como uint* no encaja bien? Estoy haciendo esta pregunta tanto para el almacenamiento como para las variables de memoria.
Supongo que para los porcentajes solo puedo usar uint y dividir por 100 internamente. Pero estoy haciendo las preguntas anteriores para los parámetros que recibirán números de punto flotante en general.
En mi opinión, es preferible adaptarse al uso de números enteros de EVM cuando sea posible. Casi siempre es posible.
Por ejemplo, aquí hay un patrón simple para manejar un porcentaje con dos números enteros de alta precisión (uno podría ser un tipo de cambio y el otro un volumen de transacciones). Primero, convierta cada entrada a un entero de 18 decimales. Entonces 1.0 sería 1 * 10 ** 18. 87% es 0.870,000,000,000,000,000, o como un número entero 870000000000000000.
Cuando multiplicas dos enteros grandes, obtienes un entero aún mayor, ya que (10 ** 18) * (10 ** 18) es 10 ** 36. Tendrás los dígitos significativos correctos y solo necesitas ajustar la posición decimal para interpretación correcta .
Considere este patrón:
pragma solidity ^0.6.6;
contract Precision {
uint constant PRECISION = 10 ** 18;
uint constant demonstrateRatio = 87 * 10 ** 16;
function percentOf(uint baseValue) public pure returns(uint result) {
return ( baseValue * demonstrateRatio ) / PRECISION;
}
}
Consejo: Siempre multiplique antes de dividir para evitar la pérdida de precisión.
Por ejemplo, reescribe lo siguiente:
x = ( a / b ) * PRECISION
como
x = ( a * PRECISION ) / b
Esto se debe a que 100/200 = 0 (con truncamiento) y 0 * PRECISIÓN = 0. Por otro lado, (100 * PRECISIÓN) / 200 da un resultado distinto de cero que se puede devolver después de ajustar la posición decimal con / PRECISION
.
Si desea un redondeo correcto, puede agregar 5 al denominador antes de dividir, lo que redondeará (correctamente) o truncará el resultado (correctamente).
x = ( a * PRECISION + 5 ) / b
Espero eso ayude.
Solidity no admite variables de punto flotante porque es más difícil ser determinista con ellas y no son las más seguras. La versión más común de decimales es tener un uint que no es un solo ETH o USD, sino 1/10^18 de uno.
Puede usar la biblioteca ABDK Math 64.64 . Opera con números binarios de punto fijo (64 dígitos binarios después del punto) y contiene todas las operaciones matemáticas básicas. Utiliza int128
el tipo para representar el número de punto fijo.
usuario19510
10^18
wei siendo1
éter), o puede usar un número racional explícito con un numerador y un denominador separados (por ejemplo,(7, 100)
significa 0.07). Este último es el enfoque adoptado aquí: programtheblockchain.com/posts/2018/02/27/… .usuario19510
uint256
.Roberto Oschler