Pages:
Author

Topic: 21million BTC is just over 51 bits of precision... (Read 4580 times)

vip
Activity: 1386
Merit: 1136
The Casascius 1oz 10BTC Silver Round (w/ Gold B)
Even though I think "TBC" is silly, if the RPC accepted strings and could either be decimal ones (1234.567) as well as hexadecimal (0x1234.567) then he'd have his Tonal Bitcoins.  It would be up to him to fork it to put those silly 19th-century Mormon Deseret Alphabet looking digits in instead of the hexadecimal the rest of us understand, but anyone who shared the legitimate concern about bitcoins being strictly divisible by ten would have it solved, this could be used to represent exact amounts from IEEE floating point as well.
1 BTC != 1 TBC. 0x1234.567 BTC is 6816.9287 TBC (6C81C6.E9287 in hexadecimal; it is also impossible, given it contains a fractional 0.7 (Tonal/hex; 0.4375 decimal) base units)

In any case, I don't want RPC to use TBC. I want it to use base units, like all internals/protocols should. Adding a ".0" to the end is only to workaround a known buggy JSON implementation.
 
6816.9287 TBC ==6C81C6.E9287 in hex?
See look you even got your own 9 confused. Isn't 9 in this tonal gibberish really a ten (0xa)?  You have used a 9 in the same spot in your tonal quantity as in hex. If the purported fact that 5+5=9 in bonal trips up even a tonal genius, imagine how much the rest of us want nothing to do with it.
legendary
Activity: 2576
Merit: 1186
Even though I think "TBC" is silly, if the RPC accepted strings and could either be decimal ones (1234.567) as well as hexadecimal (0x1234.567) then he'd have his Tonal Bitcoins.  It would be up to him to fork it to put those silly 19th-century Mormon Deseret Alphabet looking digits in instead of the hexadecimal the rest of us understand, but anyone who shared the legitimate concern about bitcoins being strictly divisible by ten would have it solved, this could be used to represent exact amounts from IEEE floating point as well.
1 BTC != 1 TBC. 0x1234.567 BTC is 6816.287 TBC (6C81C6.E9287 in hexadecimal; it is also impossible, given it contains a fractional 0.7 (Tonal/hex; 0.4375 decimal) base units)

In any case, I don't want RPC to use TBC. I want it to use base units, like all internals/protocols should. Adding a ".0" to the end is only to workaround a known buggy JSON implementation.
 
vip
Activity: 1386
Merit: 1136
The Casascius 1oz 10BTC Silver Round (w/ Gold B)
Problem is, "TBC" is your own invention, no matter how many times you repeat it.

Even though I think "TBC" is silly, if the RPC accepted strings and could either be decimal ones (1234.567) as well as hexadecimal (0x1234.567) then he'd have his Tonal Bitcoins.  It would be up to him to fork it to put those silly 19th-century Mormon Deseret Alphabet looking digits in instead of the hexadecimal the rest of us understand, but anyone who shared the legitimate concern about bitcoins being strictly divisible by ten would have it solved, this could be used to represent exact amounts from IEEE floating point as well.
legendary
Activity: 2576
Merit: 1186
If it's just the JSON api then why not fix it when it becomes a problem? Upgrading an API to a new one is not a problem as much as upgrading a protocol.
It is a problem now.

The real question is whether the precision should be made larger from int64 to int128
It is technically impossible for more than 21 million bitcoins to ever exist. int64 holds the entire quantity of base units. int128 makes no sense on a technical level. Besides, JSON only has "numbers", not int-sizes or floats. Buggy JSON implementations might try to read number-without-a-decimal-point as an int32, which is why the JSON API should require a ".0" after every number. Base units should be used because 1) valid JSON implementations might try making an imprecise float (all are, for 0.1) even when precision is needed, 2) human-readable values should be kept on the GUI, not in low-level internals like APIs, and 3) Not all Bitcoin users want to use the Decimal BitCoin (BTC) divisions.
member
Activity: 90
Merit: 10
Why does this discussion have to made over and over again?  Over the ages countless people have been burned by the practice of storing currency values in floating point, which is why nowadays it is conventional wisdom that any application handling money should never, ever use floating point types to store currency. You may think you are saving some space, or being more "efficient", or that you have enough precision, or whatever.  Resist the temptation, seriously. Just say NO!  If you don't, sooner or later that decision will come back to bite you in the ass.

Ever wonder why DBMSs have these awkward looking "numeric" types (sometimes also called "decimal"), where you explicitly specify the precision and the number of decimal places?  It's not because the DBMS people don't know of floating point.  Quite on the contrary.  They know floating point all too well, which is why they don't use it for currency.
legendary
Activity: 1232
Merit: 1076
If it's just the JSON api then why not fix it when it becomes a problem? Upgrading an API to a new one is not a problem as much as upgrading a protocol.

The real question is whether the precision should be made larger from int64 to int128

I'm sure the inventors of the internet didn't guess that ipv4 addresses would become exhausted. It's not a big deal to double the precision and much easier to change now than in the future.
Activity: -
Merit: -
Perhaps my examples are not the best, and admittedly this is outside of my area of expertise, but my main concern is that I think it goes against best practices to use floating point numbers for money.  Perhaps this is not an issue with the bitcoin client, I don't know.  Using floating point numbers still doesn't sound like a good idea to me, though.
legendary
Activity: 2576
Merit: 1186
Floating point is not good for dealing with money.

Subtracting two Doubles on the JVM:
Code:
user> (- 0.8846 0.8524)
0.032200000000000006

Subtracting two Floats on the JVM:
Code:
user> (- (float 0.8846) (float 0.8524))
0.03219998

Neither operation got the accurate answer of 0.0322.

Why floating point is being considered at all is a mystery to me.
Those are problems with decimal fractions in floats. Tonal fractions have no such problem, nor do integer values (which I was recommending). A floating-point implementation that cannot handle all possible BitCoin values as integers, is a buggy implementation. Wink
legendary
Activity: 1652
Merit: 2216
Chief Scientist
Why floating point is being considered at all is a mystery to me.

Huh?  Nobody is suggesting that any math be done with floating-point coins.

But even if we were, your first example gives the correct result to the 8-places-of-precision that Bitcoin deals with:
 (round 0.032200000000000006  to 8 places and you get 0.03220000)
Activity: -
Merit: -
Floating point is not good for dealing with money.

Subtracting two Doubles on the JVM:
Code:
user> (- 0.8846 0.8524)
0.032200000000000006

Subtracting two Floats on the JVM:
Code:
user> (- (float 0.8846) (float 0.8524))
0.03219998

Neither operation got the accurate answer of 0.0322.

Why floating point is being considered at all is a mystery to me.
legendary
Activity: 2576
Merit: 1186
Problem is, "TBC" is your own invention, no matter how many times you repeat it.
No problem at all. TBC is an adaptation of the BitCoin currency to the Tonal number system, in the same way as a port of software is an adaptation to a new platform. The only problem is when people work against innovation and progress.
legendary
Activity: 1596
Merit: 1091
Problem is, "TBC" is your own invention, no matter how many times you repeat it.
legendary
Activity: 2576
Merit: 1186
Our current interface works just fine, and all this is making a mountain out of a molehill.  I do not see the value in changing what is currently in use.
It doesn't work just fine. It is impossible to send values with sub-cent precision, and therefore also impossible to send almost any TBC coins. And just because you personally don't care about TBC is not an excuse to make life more difficult for those who do. It's no different than Windows developers trying to prevent a Linux (or Mac) port of their open source software simply by stating "it works fine for us on Windows" as an excuse to not merge patches that make it work on both platforms. The BitCoin community is growing, and not everyone is going to have the same ideals or even basic reasons for being part of the community; don't force your narrow subset of interests on everyone else whose interests might or might not overlap with yours.
donator
Activity: 826
Merit: 1039
ribuck makes a valid point why double-precision floating point does not work. To make my own example, if the exact value 3000000.00000001 (about 3M) is stored in a double-precision floating point number, it will be stored as approximately as 3000000.0000000098. Therefore doing any math on this number risks amplifying the rounding error (eg. calculating compounded interest, etc).
Sure that's true, but it's trivially worked around by storing it within the double-precision as 300000000000001 and inserting the decimal when displaying the number.

Cute quote, but the embedded world has true integers to work with; JSON-RPC does not.
legendary
Activity: 1596
Merit: 1091
If I were to rewrite the JSON-RPC interface from scratch, I would probably use strings to represent the full int64 bitcoin value, without any decimals.

But perfect is the enemy of good.

Our current interface works just fine, and all this is making a mountain out of a molehill.  I do not see the value in changing what is currently in use.
mrb
legendary
Activity: 1512
Merit: 1027
ribuck makes a valid point why double-precision floating point does not work. To make my own example, if the exact value 3000000.00000001 (about 3M) is stored in a double-precision floating point number, it will be stored as approximately as 3000000.0000000098. Therefore doing any math on this number risks amplifying the rounding error (eg. calculating compounded interest, etc).

To quote an adage from the embedded development world: "if you are using floating point, you probably have not yet understood the problem you are trying to solve".

Do not use floating point to ever store BTC quantities. Use a single 64-bit integer. Or two 32-bit integers to represent the decimal and fractional parts.

Don't store non-fractional values in floating point either. It's not even more developer-friendly than using integers. And it is a dangerous way to either accidentally forget to use double-precision everywhere, or to entice developers receiving such a value from an API to divide by 100000000 to get the decimal point in the right place, leading to inaccurate results.
legendary
Activity: 2576
Merit: 1186
As I said in the thread about possibly changing the ECDSA curve bitcoin uses, programmers like to solve "problems" that they know they can solve and that they think will make things a little bit better.  But, in my humble opinion, unless you're solving an important problem changing things because you think you know how is often a bad idea.

This is a perfect example:  change the RPC to spit out 64-bit integers (or move to a new RPC that spits out integers) and anybody using jansson on a 32-bit-int platform will get an overflow error.
OR, anyone using jansson would simply have to use (non-fractional) floats. As mentioned earlier, float types can represent the full range of base bitcoins fine, so long as they're not represented as decimal values.
I kind of like tcatm's suggestion to define new RPC methods that specify a base unit using strings... but then I thought more about it:

We could use scientific notation, so 1 BTC would be 1e08 base units; then if we ever needed more precision the JSON interface wouldn't change, you could just specify 1e-03 as a value....
... but that's exactly what we have now.  1 BTC is 1e00, 1 base unit is 1e-08, and if we ever needed more precision the JSON interface is ready.
1e8 is a perfectly legal JSON number. 1 BTC shouldn't be 1e00, it should be 1e8. And no matter how it is written (0.001 or 1e-03), the fractional-floating-point issues remain.

This works fine with the neutral branch: ./bitcoind -rpcversion=1 sendtoaddress 1KczVqwopWXQdFLe5sNQbpCq7yGSmXx2oo 1e8
legendary
Activity: 1652
Merit: 2216
Chief Scientist
That said, many libraries are smart -- such as jansson -- and will evaluate a number directly into an integer.
From the jansson docs:

"integer numbers whose absolute values are too large to be represented in the int type will result in an overflow error"

As I said in the thread about possibly changing the ECDSA curve bitcoin uses, programmers like to solve "problems" that they know they can solve and that they think will make things a little bit better.  But, in my humble opinion, unless you're solving an important problem changing things because you think you know how is often a bad idea.

This is a perfect example:  change the RPC to spit out 64-bit integers (or move to a new RPC that spits out integers) and anybody using jansson on a 32-bit-int platform will get an overflow error.

I kind of like tcatm's suggestion to define new RPC methods that specify a base unit using strings... but then I thought more about it:

We could use scientific notation, so 1 BTC would be 1e08 base units; then if we ever needed more precision the JSON interface wouldn't change, you could just specify 1e-03 as a value....
... but that's exactly what we have now.  1 BTC is 1e00, 1 base unit is 1e-08, and if we ever needed more precision the JSON interface is ready.
legendary
Activity: 1596
Merit: 1091
Actually, JSON-RPC doesn't support integer nor floating-point. It supports "number", which is not necessarily either.

Irrelevant distinction.  The definition of "number" requires support for decimal numbers.

That said, many libraries are smart -- such as jansson -- and will evaluate a number directly into an integer.
legendary
Activity: 2576
Merit: 1186
...there is no reason to use floating-point rather than a simple int64...
JSON-RPC doesn't support an Integer type. So it's floating-point or string.
Actually, JSON-RPC doesn't support integer nor floating-point. It supports "number", which is not necessarily either.
Pages:
Jump to: