Created
February 10, 2017 17:19
-
-
Save DaveAppleton/a9759c303c0e4da7fd9c012371dd269b to your computer and use it in GitHub Desktop.
NewDecimals for Solidity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A test I carried out showed that repeatedly multiplying by 1.1 finally dies when you have 1.1 ^ 70