# Get order of magnitude of an integer in solidity

What is a way of getting the order of magnitude of an integer (or float) in a solidity contract?

e.g. such that

``````MyContract.getOrderMag(2564)   returns 3
MyContract.getOrderMag(987)   returns 2
MyContract.getOrderMag(2.3e76)   returns 76
``````

Ideally in the least gas using way possible...

Here's what I have:

``````pragma solidity ^0.4.6;
contract Magger {
function getOrderMag(int256 input) constant returns (int256){
int counter=0;
int temp = input;
while((temp/10)>1){
temp = temp/10;
counter++;
}
return counter;
}
}
``````

This doesn't work with negative numbers or, as pointed out by @RichardHorrocks, when input is 10.

• Apr 20 at 14:55

Your code takes a (signed) `int256` as input. The maximum (absolute) value of this is around `1e+76`, which would equate to 76 cycles of the `while` loop, each composed of multiple instructions.

In such cases it would probably be cheaper to use a logarithmic method - i.e. take the log10 of the input and ignore any fractional parts. (I say "probably" - I haven't checked.)

It will depend on the what values you expect `input` to usually take, and how quickly the logarithm algorithm converges on an answer.

• Edit: I'd said "unsigned" instead of "signed"... Jan 11 '17 at 16:35

Here's how I did it. There is probably significant scope for improvement. I would accept any answer that uses less gas:

``````pragma solidity ^0.4.6;
contract Magger {

function getOrderMag(int256 input) constant returns (int256){
int counter=0;
if (input<0){
input=input*-1;
}
while((input/10)>=1){
input = input/10;
counter++;
}

return counter;
}
}
``````
• As it currently stands, if `input` is 10, then `counter` is 0 instead of 1 (because of the `while` condition). Jan 11 '17 at 10:57
• You could just remove the `temp` variable and use `input` in the calculation. Jan 11 '17 at 10:58
• @RichardHorrocks Thanks. Yes it's a bit broken; also doesn't work with negative numbers. Going to delete answer an post in edited question. Jan 11 '17 at 11:04
• @RichardHorrocks attempted to fix Jan 11 '17 at 11:21
• Looks good :) I've added another answer that considers the size of the input - it may or may not be relevant, depending on how big you think the input will normally be. Jan 11 '17 at 14:03
``````function magnitude (uint x) public pure returns (uint) {
require (x > 0);

uint a = 0;
uint b = 77;

while (b > a) {
uint m = a + b + 1 >> 1;
if (x >= pow10 (m)) a = m;
else b = m - 1;
}

return a;
}

function pow10 (uint x) private pure returns (uint) {
uint result = 1;
uint y = 10;
while (x > 0) {
if (x % 2 == 1) {
result *= y;
x -= 1;
} else {
y *= y;
x >>= 1;
}
}
return result;
}
``````

This implementation uses bisection and exponentiation by squaring algorithms, has O(ln^2 n) complexity and consumes about 6.5K gas. Though, it seems that O(n) approach as suggested by @atomh33ls is cheaper.