Skip to content

Instantly share code, notes, and snippets.

@DaveAppleton
Created February 10, 2017 17:19
Show Gist options
  • Save DaveAppleton/a9759c303c0e4da7fd9c012371dd269b to your computer and use it in GitHub Desktop.
Save DaveAppleton/a9759c303c0e4da7fd9c012371dd269b to your computer and use it in GitHub Desktop.
NewDecimals for Solidity
pragma solidity ^0.4.0;
// Passing in numbers must uint256 with top 248 bits representing a number and last 8 bits as a negative exponent
//
// 256 -> 1
// 2560 -> 10
// 2561 -> 1.0
// 257 -> 0.1
// 258 -> 0.01
contract test{
event ndEvent(string s, uint256 a, uint256 b, uint256 c);
struct NewDecimal {
uint256 value;
uint256 exponent;
}
function makeNewDecimal(uint256 val) constant private returns (NewDecimal v){
v.value = val /256;
v.exponent = val & 0xff;
ndEvent("Make",val,v.value,v.exponent);
}
function fromNewDecimal(NewDecimal nd) constant private returns (uint256 res) {
res = nd.value * 256 + nd.exponent;
ndEvent("From",res,nd.value,nd.exponent);
}
NewDecimal A;
NewDecimal B;
NewDecimal C;
function setA(uint256 val) {
A = makeNewDecimal(val);
}
function setB(uint256 val) {
B = makeNewDecimal(val);
}
function multiplyNewDecimal(NewDecimal a, NewDecimal b) constant private returns (NewDecimal res) {
uint256 mn = a.value * b.value;
uint exp = a.exponent + b.exponent;
if ((mn < a.value) || (mn < b.value)) {
// there was a roll around
if (a.value > b.value) {
mn = (a.value / 10) * b.value;
} else {
mn = (b.value / 10) * a.value;
}
exp++;
}
res.value = mn;
res.exponent = exp;
}
function divideNewDecimal(NewDecimal a, NewDecimal b) constant private returns (NewDecimal res) {
// a / b
while (a.value < 10000000000000000000000000000000000) { // do this better exp.1 - exp.2
a = expandNewDecimal(a,1);
}
res.value = a.value / b.value;
res.exponent = a.exponent - b.exponent;
}
function addNewDecimal(NewDecimal a, NewDecimal b) constant private returns (NewDecimal res) {
if (a.exponent > b.exponent) {
b = expandNewDecimal(b,a.exponent - b.exponent);
}
if (b.exponent > a.exponent) {
a = expandNewDecimal(a,b.exponent - a.exponent);
}
res.value = a.value + b.value;
res.exponent = a.exponent;
}
function lessThanNewDecimal(NewDecimal a, NewDecimal b) constant private returns (bool res) {
if (a.exponent > b.exponent) {
b = expandNewDecimal(b,a.exponent - b.exponent);
}
if (b.exponent > a.exponent) {
a = expandNewDecimal(a,b.exponent - a.exponent);
}
res = (a.value < b.value);
}
function subtractNewDecimal(NewDecimal a, NewDecimal b) constant private returns (NewDecimal res) {
if (a.exponent > b.exponent) {
b = expandNewDecimal(b,a.exponent - b.exponent);
}
if (b.exponent > a.exponent) {
a = expandNewDecimal(a,b.exponent - a.exponent);
}
res.value = a.value - b.value;
if (res.value != 0) {
res.exponent = a.exponent;
} else {
res.exponent = 0;
}
}
function reduceNewDecimal(NewDecimal a) constant private returns (NewDecimal res) {
if (a.value == 0) {
res.value = 0;
res.exponent = 0;
return;
}
while ((a.value % 10 == 0) && (a.exponent > 0)) {
a.value /= 10;
a.exponent -= 1;
}
res.value = a.value;
res.exponent = a.exponent;
}
function expandNewDecimal(NewDecimal a, uint256 places) constant private returns (NewDecimal res) {
if (a.value == 0) {
res.value = 0;
res.exponent = places;
return;
}
if (places > 0) {
a.value *= (10 ** places);
a.exponent += places;
}
res.value = a.value;
res.exponent = a.exponent;
}
function Add() {
C = addNewDecimal(A,B);
ndEvent("Add",fromNewDecimal(A),fromNewDecimal(B),fromNewDecimal(C));
}
function Subtract() {
C = subtractNewDecimal(A,B);
ndEvent("Sub",fromNewDecimal(A),fromNewDecimal(B),fromNewDecimal(C));
}
function Multiply() {
C = multiplyNewDecimal(A,B);
ndEvent("Mul",fromNewDecimal(A),fromNewDecimal(B),fromNewDecimal(C));
}
function Divide() {
C = divideNewDecimal(A,B);
ndEvent("Div",fromNewDecimal(A),fromNewDecimal(B),fromNewDecimal(C));
}
function getA() returns (uint256) {
return fromNewDecimal(A);
}
function getB() returns (uint256) {
return fromNewDecimal(B);
}
function getC() returns (uint256) {
return fromNewDecimal(C);
}
}
@DaveAppleton
Copy link
Author

A test I carried out showed that repeatedly multiplying by 1.1 finally dies when you have 1.1 ^ 70

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment