Pages:
Author

Topic: why JSON RPC values not use INT64 instead of float string? - page 3. (Read 18432 times)

legendary
Activity: 1470
Merit: 1006
Bringing Legendary Har® to you since 1952
I've seen problems when porting C test functions to ARM a few years ago, you definitely can't trust a floats to behave the same on all platforms.

Actually, as long as you make sure all your IEEE compliance options are turned on...

...but probably sometimes for some reason they won't be turned on...
legendary
Activity: 1596
Merit: 1100
I've seen problems when porting C test functions to ARM a few years ago, you definitely can't trust a floats to behave the same on all platforms.

Actually, as long as you make sure all your IEEE compliance options are turned on...
hero member
Activity: 602
Merit: 513
GLBSE Support [email protected]
Can you'all educate me about these mythical rounding errors that require using GMP?

Recommending that any website dealing with bitcoins compile genjix' fork and use GMP is a really good way to ensure that nobody accepts bitcoins.



Whoa there cowboy, I wasn't recommending anything, I just ansered a question, what was the genjix fork, and when asked what the best thing to do simply said what I was doing, and why.

I'm working with genjix on my project so it's not an issue for me if I use his fork, but I can't say the same for anyone else.
newbie
Activity: 45
Merit: 0
I've seen problems when porting C test functions to ARM a few years ago, you definitely can't trust a floats to behave the same on all platforms.
legendary
Activity: 1652
Merit: 2301
Chief Scientist
Can you'all educate me about these mythical rounding errors that require using GMP?

I can see, maybe, if you're computing interest down to the penny on a 30-year mortgage you might conceivably be off by a penny if you use 64-bit floats instead of 64-bit integers, although even there you're going to have to think hard about rounding as you get integer remainders.

And I can see being really careful if you're writing a bitcoin exchange site or bitcoin bank that deals in thousands of internal transactions that must all balance exactly.

But for the typical PHP website that is just going to add up 10 items in a shopping cart using plain-old PHP Numbers will be just fine.   I don't see PayPal recommending that PHP users of it's APIs install GMP.  Recommending that any website dealing with bitcoins compile genjix' fork and use GMP is a really good way to ensure that nobody accepts bitcoins.

full member
Activity: 154
Merit: 100
I don't know if it's the best way, I'm using ruby, and the whole float thing is a pain in my ass. I'm working with genjix anyway so I use his fork and avoid the entire float thing altogether.

Okay thanks... It looks like my host is able to up my PHP install to 64bit anyway.
hero member
Activity: 602
Merit: 513
GLBSE Support [email protected]
I don't know if it's the best way, I'm using ruby, and the whole float thing is a pain in my ass. I'm working with genjix anyway so I use his fork and avoid the entire float thing altogether.
full member
Activity: 154
Merit: 100
Saner branch is a genjix fork of bitcoind that returns int64 strings instead of floats or doubles in the json-api

This prevents any rounding errors associated with floats.

Cheers, still getting used to terms such as 'fork' and 'branch'.

So is this still the best way to go about it for a 32-bit PHP install? (Change seems to happen quickly in this community at the moment).

hero member
Activity: 602
Merit: 513
GLBSE Support [email protected]
Saner branch is a genjix fork of bitcoind that returns int64 strings instead of floats or doubles in the json-api

This prevents any rounding errors associated with floats.
full member
Activity: 154
Merit: 100
Anyone that prefers a saner API (because they're using PHP) should check out my branch,
https://github.com/genjix/bitcoin/tree/strrpc

Values are returned as int64 strings.
Code:
function numstr_to_internal($numstr)
{
    return bcmul($numstr, pow(10, 8), 0);
}
function internal_to_numstr($num, $precision=8)
{
    $repr = gmp_strval($num);
    $repr = bcdiv($repr, pow(10, 8), $precision);
    # now tidy output...
    # trim trailing 0s
    $repr = rtrim($repr, '0');
    # and a trailing . if it exists
    $repr = rtrim($repr, '.');
    return $repr;
}

Those are the 2 functions I use to convert from internal values to display/user input values (numstr).

I updated the wiki, https://en.bitcoin.it/wiki/API_tutorial_%28JSON-RPC%29#PHP


Reading this at the moment... https://en.bitcoin.it/wiki/API_reference_(JSON-RPC)

Under 'Precision' you wrote:

You will need to get a saner branch and compile it.
https://github.com/genjix/bitcoin/tree/strrpc

Does 'saner branch' mean get a good version of GMP? I don't quite get what the phrase refers to.
legendary
Activity: 1470
Merit: 1006
Bringing Legendary Har® to you since 1952
sorry it was a typo. supposed to say 5.01

Probably a buggy version of PHP.

Anyway, on a lot of hosting providers have old versions of PHP installed (there are older versions in many distros' repositories), so it may be dangerous to use floats.
This is one of the reasons why i said initially that floats are dangerous as hell.
sr. member
Activity: 294
Merit: 252
The PHP manual says that float=double.

Wouldn't gavin's solution of "float * 1e8" work?
legendary
Activity: 1232
Merit: 1076
sorry it was a typo. supposed to say 5.01

The point was that PHP is casting to floats in their JSON decoder and there's no option to use doubles or strings.
legendary
Activity: 1652
Merit: 2301
Chief Scientist
PHP 5.3.3. on my mac gives:
Code:
object(stdClass)#1 (1) {
  ["e"]=>
  float(5.01)
}

Please be specific about what platform you're running on, what version of PHP are you running, are you running with a standard php.ini or have you tweaked it, etc.
legendary
Activity: 1470
Merit: 1006
Bringing Legendary Har® to you since 1952
My result:

Code:
object(stdClass)#1 (1) {
  ["e"]=>
  float(5.01)
}

Checked on 2 separate PHP Versions : 5.3.5 and 5.2.14

Different versions, different results ?
legendary
Activity: 1232
Merit: 1076
Try this:

Code:
$json '{"e":5.01}';
var_dump(json_decode($json));
?>


Output:

Code:
object(stdClass)#1 (1) { ["e"]=> float(5.01) }

legendary
Activity: 1652
Merit: 2301
Chief Scientist
It does not work that way ..  printf("%.8f") behaviour is inconsistent across platform. If you don't believe, try

Code:
printf("%.2f", -999.04)

-- some platform give  -999.03, some give -999.04.

I tried it... got -999.04 on my Mac and Linux machines.  What platform gives the wrong answer?
newbie
Activity: 37
Merit: 0
....
Quote
> php -r "printf('%.8f', 0.94);"    #CORRECT
0.94000000
> php -r "printf('%.16f', 0.94);"   #WRONG
0.9399999999999999
....


It does not work that way ..  printf("%.8f") behaviour is inconsistent across platform. If you don't believe, try

Code:
printf("%.2f", -999.04)

-- some platform give  -999.03, some give -999.04.

Of course, you can fix this.... in your code. (But never expect all 3rd party apps do it right)
legendary
Activity: 1470
Merit: 1006
Bringing Legendary Har® to you since 1952
All serious institutions (like banks) never use floats for currency calculations because they know the dangers.
If we want to be seen as "serious", float is not an option.

You know, I was looking at the PayPal payment API yesterday, and $1.01 is sent as... 1.01

"transmitting" != "calculations"

Of course you're right.
I was merely stating the fact.
legendary
Activity: 1652
Merit: 2301
Chief Scientist
All serious institutions (like banks) never use floats for currency calculations because they know the dangers.
If we want to be seen as "serious", float is not an option.

You know, I was looking at the PayPal payment API yesterday, and $1.01 is sent as... 1.01

"transmitting" != "calculations"
Pages:
Jump to: