Bitcoin Forum
May 22, 2024, 02:31:31 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Why is this code yielding something like this?  (Read 238 times)
CounterEntropy (OP)
Full Member
***
Offline Offline

Activity: 214
Merit: 278


View Profile
June 18, 2022, 05:20:47 PM
 #1

I am using the following PHP code...

Code:
echo round(($satoshiValue/pow(10,8)),8);

When, $satoshiValue = 10000, result is 0.0001 as expected.

But, when, $satoshiValue = 10000000, result is 0.10000000000000001. Expected was 0.1 though.

Why is this happening?


p.s. I could not find a better place to ask this question on BitcoinTalk. So, asking it here. If mods think, it does not fit here, feel free to move.
BlackHatCoiner
Legendary
*
Online Online

Activity: 1526
Merit: 7408


Farewell, Leo


View Profile
June 18, 2022, 05:45:16 PM
 #2

With:
Code: ("test.php")
$satoshiValue = 10000000;
echo round(($satoshiValue/pow(10,8)),8);

I get:
Code:
0.1

See: https://blackhatcoiner.com/5403124/test

What PHP version do you use? Mine is 7.4.

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
jackg
Copper Member
Legendary
*
Offline Offline

Activity: 2856
Merit: 3071


https://bit.ly/387FXHi lightning theory


View Profile
June 18, 2022, 05:47:11 PM
 #3

It's an underflow error. I'm not used to php but you might be able to search that and find an optimal solution for how to represent the numbers.

If you can't find a solution, bitcoin core stores numbers in bitcoin it uses as the number of satoshi and then just puts a decimal place between the 8th and 9th index.

I'd advise this belong in development and technical discussion also.
vv181
Legendary
*
Offline Offline

Activity: 1932
Merit: 1273


View Profile
June 18, 2022, 05:58:01 PM
Merited by CryptopreneurBrainboss (4), NotATether (3), theymos (2), ABCbits (1), hosseinimr93 (1), DdmrDdmr (1), Husna QA (1)
 #4

Why is this happening?

Warning
Floating point precision

Floating point numbers have limited precision. Although it depends on the system, PHP typically uses the IEEE 754 double precision format, which will give a maximum relative error due to rounding in the order of 1.11e-16. Non elementary arithmetic operations may give larger errors, and, of course, error propagation must be considered when several operations are compounded.

Additionally, rational numbers that are exactly representable as floating point numbers in base 10, like 0.1 or 0.7, do not have an exact representation as floating point numbers in base 2, which is used internally, no matter the size of the mantissa. Hence, they cannot be converted into their internal binary counterparts without a small loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation will be something like 7.9999999999999991118....

So never trust floating number results to the last digit, and do not compare floating point numbers directly for equality. If higher precision is necessary, the arbitrary precision math functions and gmp functions are available.

For a "simple" explanation, see the » floating point guide that's also titled "Why don’t my numbers add up?"
hosseinimr93
Legendary
*
Offline Offline

Activity: 2408
Merit: 5243



View Profile
June 18, 2022, 06:18:36 PM
 #5

I am not much familiar with PHP.
I just made a search and found an article which seems to be helpful to anyone who wants to know what's causing the issue.
Why 0.1 Does Not Exist In Floating-Point

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
NotATether
Legendary
*
Online Online

Activity: 1610
Merit: 6753


bitcoincleanup.com / bitmixlist.org


View Profile WWW
June 19, 2022, 04:12:32 AM
 #6

Why is this happening?

Warning
Floating point numbers have limited precision. Although it depends on the system, PHP typically uses the IEEE 754 double precision format, which will give a maximum relative error due to rounding in the order of 1.11e-16. Non elementary arithmetic operations may give larger errors, and, of course, error propagation must be considered when several operations are compounded.

You can always use floating-point precision if possible by rounding to 6 digits (most people will never need more than 6 digits of precision) using a neat scaling-up trick:

Code:
$num = $1.00000001;
$scaling_factor = $1000000;
$num = round($num * $scaling_factor) / $scaling_factor;
echo $num; # 1.000000

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
theymos
Administrator
Legendary
*
Offline Offline

Activity: 5208
Merit: 12998


View Profile
June 19, 2022, 07:24:10 AM
Last edit: June 19, 2022, 07:53:47 AM by theymos
Merited by LoyceV (2), hosseinimr93 (2), ABCbits (1), DdmrDdmr (1), Husna QA (1), BlackHatCoiner (1), CounterEntropy (1)
 #7

As others have mentioned, when you're dealing with floating-point numbers, different numbers can have the same internal representation. 10000000/pow(10,8) returns 0.1, but because this is stored as a floating-point number, it has the same byte-level representation as 0.10000000000000001 as well as infinitely many other numbers, and when echo converts this float to a string, it chooses that particular value to display. round returns a float, so that doesn't fix the issue: in this case it outputs exactly the same thing that it takes as input.

sprintf('%.8f', $satoshiValue/pow(10,8)) will do what you expected round to do because it returns a string instead of a float. There are other ways to address the issue, but that's what I'd do.

What PHP version do you use? Mine is 7.4.

The exact behavior of floats might depend on the CPU, OS, compiler, C library, and PHP version. You can't rely on any specific behavior.

1NXYoJ5xU91Jp83XfVMHwwTUyZFK64BoAD
DannyHamilton
Legendary
*
Offline Offline

Activity: 3388
Merit: 4653



View Profile
June 21, 2022, 02:13:31 PM
Merited by LoyceV (4), ABCbits (1), PrimeNumber7 (1)
 #8

When working with money, it's almost always best to work with integers. Don't store your value as a number of bitcoins. Store it as a number of satoshis. Anytime you are performing an operation that may return a fractional quantity of satoshis, make sure that you have decided what the proper rounding process is for your use case (floor, ceiling, round, etc), and then convert the result to an integer using your chosen method.

If you want to display the result as a number of bitcoins (or millibitcoins, or microbitcoins), convert to the display value at the time of display using an output formatting function to restrict the displayed value to no more than the number of decimals that represent the original value.
NotATether
Legendary
*
Online Online

Activity: 1610
Merit: 6753


bitcoincleanup.com / bitmixlist.org


View Profile WWW
June 22, 2022, 04:50:04 AM
 #9

The exact behavior of floats might depend on the CPU, OS, compiler, C library, and PHP version. You can't rely on any specific behavior.

It's more influenced by C compiler (and consequently the OS, as they have wildly different compilers) than anything else because that is the area where the multiplications and divisions are transformed to ASM instructions.

C library doesn't play a part here unless you - and consequentially the language's library routines - makes use of pow() or other glibc math function.

Pretty much the entire Pentium class of CPUs and derivatives divide numbers wrongly giving the same error remainders, or sites like 0.30000000000004 would not be able to give generic information about the problem, with people's vastly different CPU models.

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!