mIRC Home    About    Download    Register    News    Help

Print Thread
Joined: Dec 2002
Posts: 252
T
Talon Offline OP
Fjord artisan
OP Offline
Fjord artisan
T
Joined: Dec 2002
Posts: 252
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
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 }
}

Joined: Dec 2002
Posts: 5,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
Thanks for your bug report. Unfortunately, I cannot quite make out the issue you are reporting.

Are you saying that $base() is returning an incorrect result?

Or $tbase() is returning an incorrect result?

Or that $calc() and/or $round() are returning incorrect results?

If the issue is due to rounding >=30 decimal places, I am not sure if there is a way around that, since rounding always leads to loss of precision and changes the results of subsequent calculations. The amount of precision used internally is always going to be greater than that used in scripts because a script will always receive results with at most 30 decimal places in bigfloat mode and 6 decimal places in non-bigfloat mode. You are comparing $base(), which is a native implementation that uses as many decimal places as are available until returning the final result, with $tbase() which is a script that uses at most 30 decimal place values during its calculations, if I understand your post correctly.

Update: In your example, it turns out that $base() was internally rounding at 30 decimal places in interim calculations. I have extended the decimal places a little for interim calculcations which resolves the $base() issue when using 30 decimal place big floats. This change will be in the next beta.


Link Copied to Clipboard