# Conum

EXTREME WORK IN PROGRESS

{ I just got the idea, gonna leave some drafts here for now. }

Conum (for *common number*) is a work in progress format/[data type](data_type.md) for [computer](computer.md) representation of [numbers](number.md), or rather a parameterized class of such types which allow to simply specify all commonly used types of numbers, including signed and unsigned integers, [fixed](fixed_point.md) and [floating](float.md) point numbers etc. This was thought up by [drummyfish](drummyfish.md), but it's possible that someone else already invented it because it's pretty simple and obvious. This should be the ultimate, [minimalist](minimalism.md), most [beautiful](beauty.md) way of handling numbers and as such may end up being used in the [public domain computer](public_domain_computer.md).

## The Gist

IT'S ALL IN THE STATE OF A ROUGH IDEA NOW

the basic approach:

1. Create a "[logarithmic](log.md)" unsigned integer type with one parameter saying the "amount" to which it is logarithmic. If this parameter is 0, it reduces to normal, linear integers.
2. Add another parameter that simply states the number of fixed fractional bits. Again, 0 will result in a purely integer type, higher values will create either fixed point (with linear integers) or floating point (otherwise).
3. Add another parameter specifying the way of representing sign. This may include no sign, single sign bit, one's complement and [two's complement](twos_complement.md).

A number will be represented by *N* bits, out of which *E* are reserved for "exponent" value (*e*) and *B* for "base" value (*b*). For example a 5 bit type with *E = 3* will look like this:

```
e2 e1 e0 b1 b0
```

Considering only unsigned integers now, the number this represents is:

```
x = (2^B + b) * 2^e - 2^B
```

Basically imagine this: to decode a number, write down 1 and follow it by the *b* bits, for example for a value (5 bit with *E = 3*) `01010` start by writing `110`. Then shift this all left by *e* and subtract *100*, i.e. `110 << 10 = 11000` and `11000 - 100 = 10100` (the subtraction is here because otherwise the lowest number we could represent would be `100`, so we just subtract it). So the original value represents the number 20. This creates a number series that increases more and more rapidly (how quickly depends on *E* we set). Here is a small example of how 5 bit values interpret under different settings of *E* (note that 0 gives just normal integers):

| bit str.| E = 0 | E = 1       | E = 2         | E = 3            |   
| ------- | ----- | ----------- | ------------- | ---------------- |
|  00000  | 0     |  0 (000000) |   0 (0000000) |   0 (0000000000) |
|  00001  | 1     |  1 (000001) |   1 (0000001) |   1 (0000000001) |
|  00010  | 2     |  2 (000010) |   2 (0000010) |   2 (0000000010) |
|  00011  | 3     |  3 (000011) |   3 (0000011) |   3 (0000000011) |
|  00100  | 4     |  4 (000100) |   4 (0000100) |   4 (0000000100) |
|  00101  | 5     |  5 (000101) |   5 (0000101) |   6 (0000000110) |
|  00110  | 6     |  6 (000110) |   6 (0000110) |   8 (0000001000) |
|  00111  | 7     |  7 (000111) |   7 (0000111) |  10 (0000001010) |
|  01000  | 8     |  8 (001000) |   8 (0001000) |  12 (0000001100) |
|  01001  | 9     |  9 (001001) |  10 (0001010) |  16 (0000010000) |
|  01010  | 10    | 10 (001010) |  12 (0001100) |  20 (0000010100) |
|  01011  | 11    | 11 (001011) |  14 (0001110) |  24 (0000011000) |
|  01100  | 12    | 12 (001100) |  16 (0010000) |  28 (0000011100) |
|  01101  | 13    | 13 (001101) |  18 (0010010) |  36 (0000100100) |
|  01110  | 14    | 14 (001110) |  20 (0010100) |  44 (0000101100) |
|  01111  | 15    | 15 (001111) |  22 (0010110) |  52 (0000110100) |
|  10000  | 16    | 16 (010000) |  24 (0011000) |  60 (0000111100) |
|  10001  | 17    | 18 (010010) |  28 (0011100) |  76 (0001001100) |
|  10010  | 18    | 20 (010100) |  32 (0100000) |  92 (0001011100) |
|  10011  | 19    | 22 (010110) |  36 (0100100) | 108 (0001101100) |
|  10100  | 20    | 24 (011000) |  40 (0101000) | 124 (0001111100) |
|  10101  | 21    | 26 (011010) |  44 (0101100) | 156 (0010011100) |
|  10110  | 22    | 28 (011100) |  48 (0110000) | 188 (0010111100) |
|  10111  | 23    | 30 (011110) |  52 (0110100) | 220 (0011011100) |
|  11000  | 24    | 32 (100000) |  56 (0111000) | 252 (0011111100) |
|  11001  | 25    | 34 (100010) |  64 (1000000) | 316 (0100111100) |
|  11010  | 26    | 36 (100100) |  72 (1001000) | 380 (0101111100) |
|  11011  | 27    | 38 (100110) |  80 (1010000) | 444 (0110111100) |
|  11100  | 28    | 40 (101000) |  88 (1011000) | 508 (0111111100) |
|  11101  | 29    | 42 (101010) |  96 (1100000) | 636 (1001111100) |
|  11110  | 30    | 44 (101100) | 104 (1101000) | 764 (1011111100) |
|  11111  | 31    | 46 (101110) | 112 (1110000) | 892 (1101111100) |

Now the point is that this is quite elegant, simple, backwards compatible generalization of direct representation of binary numbers, which can further very easily be extended to fixed and floating point merely by considering some given number of the represented number's bits as fractional, plus we can also quite trivially add sign e.g. by literally taking two's complement (which will solve he issue of double zeros etc.). It's super general and overcomplicated like [posits](posit.md) (which have variable size fields and require a whole paper to be explained).

TO BE CONTINUED

## See Also

- [comun](comun.md)
