Bigfloat/$base() rounding with 30+ decimal places - 28/11/22 04:20 AM
Here is my test to compare results of $base from mIRC to my own implementation. When numbers with <= 29 decimal places are passed, both perform identical. When a number is passed > 29 decimal places, the end result is different.
My only theory is that the new mathematical operations do not trim/round a passed number to the proposed 29 decimal places before performing operations yet the return result is truncated/rounded to this limit which can skew subsequent operations on the return result of the first calculation. I sort-of prove this theory by example 2 forcing passed numbers to be <= 29 decimal places, which is why $tbase() is wrong in instances where decimals exceed 29. and does not match mIRC's $base()
I could be wrong but I believe $calc() did this before bigfloat where numbers were trimmed/rounded to 6 decimal places before calculating.
Side-Note: It appears $base() will vary from 29 to 30 in decimal places in my tests. Even in this example the decimal length varies from 29-30.
$TBase() Conversion method with decimals applied from reading this article:
https://www.mathsisfun.com/base-conversion-method.html
The alphabets used are a direct copy from maroon's $qbase()
Test with decimal > 29
//clear | bftest
Test with decimal <= 29 (just round pi first to 29 places)
//clear | bftest 1
And here is the code required to run this test...
My only theory is that the new mathematical operations do not trim/round a passed number to the proposed 29 decimal places before performing operations yet the return result is truncated/rounded to this limit which can skew subsequent operations on the return result of the first calculation. I sort-of prove this theory by example 2 forcing passed numbers to be <= 29 decimal places, which is why $tbase() is wrong in instances where decimals exceed 29. and does not match mIRC's $base()
I could be wrong but I believe $calc() did this before bigfloat where numbers were trimmed/rounded to 6 decimal places before calculating.
Side-Note: It appears $base() will vary from 29 to 30 in decimal places in my tests. Even in this example the decimal length varies from 29-30.
$TBase() Conversion method with decimals applied from reading this article:
https:/
The alphabets used are a direct copy from maroon's $qbase()
Test with decimal > 29
//clear | bftest
Code
* $Pi: 3.14159265358979323846264338327950288419716939937510582 * m Hex Pi: 3.243F6A8885A308D313198A2E0D859F * t Hex Pi: 3.243F6A8885A308D313198A2DF93D53 base16 != tbase16 ---------------------------------------------------------- $base m Hex Pi: 3.14159265358979323846264338328 $base t Hex Pi: 3.141592653589793238462643383279 ---------------------------------------------------------- tbase m Hex Pi: 3.141592653589793238462643383282 tbase t Hex Pi: 3.14159265358979323846264338328 ---------------------------------------------------------- * Calculated Pi: 3.14159265358979323846264338328 * m Hex Calc Pi: 3.243F6A8885A308D313198A2E0D859F * t Hex Calc Pi: 3.243F6A8885A308D313198A2E0D859F base == tbase
Test with decimal <= 29 (just round pi first to 29 places)
//clear | bftest 1
Code
* Rounded $Pi: 3.14159265358979323846264338328 * m Hex Pi: 3.243F6A8885A308D313198A2E0D859F * t Hex Pi: 3.243F6A8885A308D313198A2E0D859F base == tbase * Calculated Pi: 3.14159265358979323846264338328 * m Hex Calc Pi: 3.243F6A8885A308D313198A2E0D859F * t Hex Calc Pi: 3.243F6A8885A308D313198A2E0D859F base == tbase
And here is the code required to run this test...
Code
;=============================== ; $tbase(N,in,out,pad,precision) ;=============================== alias tbase { if ($beta || $version > 7.71) { .bigfloat on } var %alphabet.36 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ var %alphabet.52 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz var %alphabet.62 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz var %alphabet.64 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ var %alphabet.85 !&'*+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{}~ if ($2 isnum 2-36) { var %in $mid(%alphabet.36,1,$2) , %i = 1 } elseif ($2 == 52) { var %in %alphabet.52 , %i = 0 } elseif ($2 isnum 37-62) { var %in $mid(%alphabet.62,1,$2) , %i = $iif($len(%in) > 36,1,0) } elseif ($2 == 85) { var %in %alphabet.85 , %i = 0 } elseif ($2 isnum 63-64) { var %in $mid(%alphabet.64,1,$2) , %i = $iif($len(%in) > 26,1,0) } if ($3 isnum 2-36) { var %out $mid(%alphabet.36,1,$3) } elseif ($3 == 52) { var %out %alphabet.52 } elseif ($3 isnum 37-62) { var %out $mid(%alphabet.62,1,$3) } elseif ($3 == 85) { var %out %alphabet.85 } elseif ($3 isnum 63-64) { var %out $mid(%alphabet.64,1,$3) } var %depth = $iif($5 isnum,$5,$iif($beta || $version > 7.71,30,6)) if ($regex($1,/^([^\x2e]+).?(.*)$/)) { var %int = $regml(1) , %dec = $regml(2) , %l = 0 } var %x = 0 , %a = 0 , %lenInt = $len(%int) while (%x < %lenInt) { inc %x inc %a $calc(($iif(%i,$pos(%in,$mid(%int,%x,1),1),$poscs(%in,$mid(%int,%x,1),1))-1)*$len(%in)^(%lenInt - %x)) } var %x = 0 , %b = 0 , %lenDec = $len(%dec) while (%x < %lenDec) { inc %x inc %b $calc(($iif(%i,$pos(%in,$mid(%dec,%x,1),1),$poscs(%in,$mid(%dec,%x,1),1))-1) / $len(%in) ^ %x) } while ($int(%a)) && ($len(%out)) { var %c $mid(%out,$calc(%a % $v1 +1),1) $+ %c,%a %a / $v1 } while (%b > 0 && %l < %depth) && ($len(%out)) { var %d %d $+ $mid(%out,$calc(%b * $v1 +1),1),%b $calc((%b * $v1) % 1),%l %l + 1 } var %ret = %c $+ $iif(%d != $null,. $+ %d) if ($4 && $len(%ret) < $4) { return $+($str(0,$calc($4 - $v1)),%ret) } return %ret } alias bftest { .bigfloat on var %pi = $iif($1,$round($pi,29),$pi) var %hpi = $base(%pi,10,16) , %hcpi = $base($calc($atan(1)*4),10,16) var %tpi = $tbase(%pi,10,16) , %tcpi = $tbase($calc($atan(1)*4),10,16) echo -si2 * $iif($1,Rounded) $!Pi: %pi echo -si2 * m Hex Pi: %hpi echo -si2 * t Hex Pi: %tpi if (%hpi != %tpi) { echo 4 -si2 base16 != tbase16 echo -si2 ---------------------------------------------------------- echo -si2 $!base m Hex Pi: $base(%hpi,16,10) echo -si2 $!base t Hex Pi: $base(%tpi,16,10) echo -si2 ---------------------------------------------------------- echo -si2 tbase m Hex Pi: $tbase(%hpi,16,10) echo -si2 tbase t Hex Pi: $tbase(%tpi,16,10) echo -si2 ---------------------------------------------------------- } else { echo -si2 base == tbase } echo -si2 * Calculated Pi: $calc($atan(1)*4) echo -si2 * m Hex Calc Pi: %hcpi echo -si2 * t Hex Calc Pi: %tcpi if (%hcpi != %tcpi) { echo 4 -si2 base != tbase echo -si2 ---------------------------------------------------------- echo -si2 $!base m Hex Calc Pi: $base(%hcpi,16,10) echo -si2 $!base t Hex Calc Pi: $base(%tcpi,16,10) echo -si2 ---------------------------------------------------------- echo -si2 tbase m Hex Calc Pi: $tbase(%hcpi,16,10) echo -si2 tbase t Hex Calc Pi: $tbase(%tcpi,16,10) echo -si2 ---------------------------------------------------------- } else { echo -si2 base == tbase } }