Bin won't display more than 53 bits?

New to FreeBASIC? Post your questions here.
Post Reply
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Bin won't display more than 53 bits?

Post by Tourist Trap »

Hi

It's a long time I've not used BIN to exhibit a binary integer , and I was sure I was able in the past to play with any integer up to 2^64 - 1, or 2^63 - 1. The 63 or 64 here is not important, what I dont understand is why it wont go beyond 2^53 - 1 ( lot less than what ulongint would allow).

Code: Select all

'win10  64
? bin(cUlngint(2^53 - 1))   '111.... up to 53 digits as expected

? bin(cUlngint(2^54 - 1))  '1000.... not good!

sleep
What am I missing, I used cUlngint here to be sure the compiler wont troncate the value to something like a double. Whatever, I really think I used this in the past and it worked up to 63 or 64.

Can someone enlight me here please ? Be thanked by advance!
fxm
Moderator
Posts: 12108
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Bin won't display more than 53 bits?

Post by fxm »

Same behavior since version FBC 0.14b.
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: Bin won't display more than 53 bits?

Post by Tourist Trap »

fxm wrote:Same behavior since version FBC 0.14b.
Yes, but still surprising. Only after some manipulations I finally solved this myself. It's a quite delicate affair of parenthesis. For some reason 2^n with n>53 will not be converted too well to a longint. It is able to go beyond 32 but wont then assume that this means 64.

Ok, that was not so obvious. Here is what works:

Code: Select all

? bin(cUlngint( 2^64 ) - 1)
(to make it clear, for me the 53 bits limit is irrelevant, or it's 32 bits or it's 64, for we work with integers)

In conclusion if one doesn't know what will be the length he will need to render when using Bin, I think that the conversion operator should be associated to the use of BIN by the coder in all cases.
- Beyond 64 bits of course it's another issue.

Correct me if I'm wrong of course.
fxm
Moderator
Posts: 12108
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Bin won't display more than 53 bits?

Post by fxm »

Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: Bin won't display more than 53 bits?

Post by Tourist Trap »

fxm wrote:See Operator ^ (Exponentiate), and DOUBLE.
At BIN page, we find this sentence that can lead someone to think that any argument will be or a long or a longint for BIN:
The length of the string will not go longer than the maximum number of digits required for the type of number (32 for a long, 64 for a Longint.)
I understand of course that exponentiate will return a double, that's just difficult to think of it in this context when we use 2^N with BIN. Base = 2 for both of them after all.
Maybe it's up to the coder to take care of the conversion. It's not immediately visible however in my opinion.
badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Bin won't display more than 53 bits?

Post by badidea »

Code: Select all

? bin(cUlngint(1 shl 53 - 1))
? bin(cUlngint(1 shl 54 - 1))
(although not allowed on my 32-bit fbc)
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: Bin won't display more than 53 bits?

Post by Tourist Trap »

badidea wrote:

Code: Select all

? bin(cUlngint(1 shl 53 - 1))
? bin(cUlngint(1 shl 54 - 1))
Nice trick, even if I don't understand it. We can't reach 55 this way but the 53 limit is passed ;)

By the way I'm just noticing right now that LOG won't work with ulongint above the 2^53 too. Because it is designed to take DOUBLE as argument. So LOG(2^64)/LOG(2) fails. It would simply return 64. I wonder if there is known systematic workaround for integer arithmetics hidden in log and exp. A compiler optimisation?
fxm
Moderator
Posts: 12108
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Bin won't display more than 53 bits?

Post by fxm »

Extract of the documentation:
Double contains at most 53 bits of precision.
Doubles have limited accuracy which can lead to significant inaccuracies if not used properly. They are dyadic numbers - i.e. they can only accurately hold multiples of powers of two (exact value for '2^n', but only 53 bits of precision for '2^n - 1').
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: Bin won't display more than 53 bits?

Post by Tourist Trap »

fxm wrote:Extract of the documentation:
Double contains at most 53 bits of precision.
Doubles have limited accuracy which can lead to significant inaccuracies if not used properly. They are dyadic numbers - i.e. they can only accurately hold multiples of powers of two (exact value for '2^n', but only 53 bits of precision for '2^n - 1').
Thanks, that reassures me. I had powers of 2 in mind.

I fall on logarithms because I thought that in order to write a code made essentially around powers of 2, I could introduce some testing like this:

Code: Select all

dim as ulongint u
'we want to assign u = a^b but not without some check-up
scope
    dim as integer a = rnd()*2^32
    dim as integer b = rnd()*2^32
    if a<>2 then
       dim as ulongint x = b*log(a)/log(2)
       if x>53 then ? "warning v > 2^53 "
       v = a^b
     else
       if b >53 then ? "warning..."
       v = 2^b
    end if
end scope
(I assumed that beyond 2^53 I should be warned in order to take care, but of course it doesn't promise me that I'll be able to get things working up to 64 bits integers here)

But if the log function itself has to be surveyed, it disturbs me :)

Other thing:
The following behaviour is weird:

Code: Select all

dim as ulongint a = cUlngint(2^64) - 1
? bin(a, 64)   'ok

for iter = 1 to 10
   dim as ulongint a = rnd()*2^64
   ? bin(a, 64)
next iter

for iter = 1 to 10
   dim as ulongint a = rnd()*2^64
   ? bin(a, 64)
next iter

sleep
It's like if rnd() had the effect to restrict the result stored in a, to a 32 bits long thing, with a start at the max bit exponent, and an end at max - 32 (unless max<=32)...
I don't see why. A 53 bits long result would have been less surprising, but it seems to be 32 bits or am I hallucinating?
badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Bin won't display more than 53 bits?

Post by badidea »

Not sure what you are trying to build, but 'asm bsr' (bit scan reverse) is practically log2 for integers.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Bin won't display more than 53 bits?

Post by dodicat »

TT
I don't think that bin is the problem
It seems to be the way a double is returned.

Code: Select all

Function plus(Byval num1 As String,Byval num2 As String) As String
    Static As Const Ubyte AddQMod(0 To 19)={48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57}
    Static As Const Ubyte AddBool(0 To 19)={0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1}
    Var n_=0
    Dim As Ubyte addup=Any,addcarry
    #macro finish()
    Return Ltrim(answer,"0")
    #endmacro
    If Len(num2)>Len(num1) Then  Swap num2,num1
    Var diff=Len(num1)-Len(num2)
    Var answer="0"+num1
    For n_=Len(num1)-1 To diff Step -1 
        addup=num2[n_-diff]+num1[n_]-96
        answer[n_+1]=ADDQmod(addup+addcarry)
        addcarry=ADDbool(addup+addcarry)
    Next n_ 
    If addcarry=0 Then 
        finish()
    End If
    If n_=-1 Then 
        answer[0]=addcarry+48
        finish()
    End If
    For n_=n_ To 0 Step -1 
        addup=num1[n_]-48
        answer[n_+1]=ADDQmod(addup+addcarry)
        addcarry=ADDbool(addup+addcarry)
        If addcarry=0 Then Exit For
    Next n_
    answer[0]=addcarry+48
    finish()
End Function


Function minus(byval num1 As String,byval num2 As String) As String
    Static As Const Ubyte subqmod(19)={48,49,50,51,52,53,54,55,56,57,48,49,50,51,52,53,54,55,56,57}
    Static As Const Ubyte subbool(19)={1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}
    Dim As Integer bigger          
    Dim sign As String * 1
    Var lenf=Len(NUM1)
    Var lens=Len(NUM2)
    #macro finishup()
    answer=Ltrim(answer,"0")
    If answer="" Then Return "0"
    Return sign+answer
    #endmacro
    #macro compare()
    If Lens>lenf Then bigger= -1:Goto fin
    If Lens<lenf Then bigger =0:Goto fin
    If NUM2>NUM1 Then 
        bigger=-1
    Else
        bigger= 0
    End If
    fin:
    #endmacro
    
    compare()
    If bigger Then 
        sign="-"
        Swap NUM2,NUM1
        Swap lens,lenf
    End If
    Var diff=lenf-lens
    Dim As String answer=NUM1
    Dim As Integer n
    Dim As Ubyte takeaway,subtractcarry
    subtractcarry=0
    For n=lenf-1 To diff Step -1 
        takeaway= num1[n]-num2[n-diff]+10-subtractcarry
        answer[n]=Subqmod(takeaway)
        subtractcarry=Subbool(takeaway)
    Next n 
    
    If subtractcarry=0 Then:finishup():End If
    If n=-1 Then:finishup():End If
    For n=n To 0 Step -1 
        takeaway= num1[n]-38-subtractcarry 
        answer[n]=Subqmod(takeaway)
        subtractcarry=Subbool(takeaway)
        If subtractcarry=0 Then Exit For
    Next n
    finishup()
End Function  

Function rndX (s1 As String) As String
    #macro GetNumber
    #define range(f,l) Int(Rnd*((l+1)-(f))+(f))
    s[0]=range(48,s1[0])
    For n As Long = 1 To L-1
        s[n]=range(48,57)
    Next
    #endmacro
    #macro compare(n1,n2,ans)
    Scope
        Var lenn1=Len(n1),lenn2=Len(n2)
        If lenn1 > lenn2 Then ans=-1:Goto lbl
        If lenn1 < lenn2 Then ans=0:Goto lbl
        If n1 > n2 Then ans = -1  Else ans= 0
        lbl:
    End Scope
    #endmacro
    Dim As Long L=Len(s1),ans=1
    Dim As String s=String(L,0)
    While ans
        GetNumber
        compare(s,s1,ans)
    Wend
    Return Ltrim(s,"0")
End Function

 Function base2(DecimalNumber As String) As String
            Dim As String starter=DecimalNumber,ans,m,b
            Dim As Ubyte main,carry,temp',c
            Dim As Integer c
            #macro reverse(s)
                Scope
                var lens=Len(s)
                For n As Integer=0 To Int((lens-1)/2):Swap s[n],s[lens-1-n]:Next
                End Scope
                #endmacro
                #macro div2(s,m,c)
                carry=0:ans=s
                For z As Integer=0 To Len(s)-1
                    temp=(s[z]-48+carry)
                    main=temp Shr 1
                    carry=(temp And 1) Shl 3 +(temp And 1) Shl 1
                    ans[z]=main+48
                Next z
                c= carry\10
                m= Ltrim(ans,"0")
                #endmacro
                Do
                    c=0
                    div2(starter,m,c)
                    b=b+Str(c)
                    starter=m
                Loop Until m="1"
                reverse(b)
                b=Str(m)+b
                Return b
         End Function
         

dim as ulongint a = culngint(2^64) - 1
? bin(a, 64)   'ok

randomize 2

print
print "Pure big ulongint and fb bin 64 digits"
dim as long iter
for iter = 1 to 10
    dim as string s=rndX("18446744073709551616")
   dim as ulongint a = valulng(s)'=(rnd()*2^64)
   ? bin(a, 64),a
next iter
print
print "Alternative bin for ulongint derived from a double"
randomize 2
for iter = 1 to 10
   dim as ulongint a = rnd()*2^64
   ? base2(str(a)),a
next iter
print
print "FB bin for ulongint derived from a double"
randomize 2
for iter = 1 to 10
   dim as ulongint a = rnd()*2^64
   ? bin(a),a
next iter
print

print "Alternative bin for ulongint derived from a double via str()"
randomize 2
for iter = 1 to 10
    dim as string u=str(rnd()*2^64)
   dim as ulongint a = val(u)
   ? base2(str(a)),a
next iter
print
print "FB bin for ulongint derived from a double via str()"

randomize 2
for iter = 1 to 10
    dim as string u=str(rnd()*2^64)
   dim as ulongint a = val(u)
   ? bin(a),a
next iter
print




sleep 
fxm
Moderator
Posts: 12108
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Bin won't display more than 53 bits?

Post by fxm »

Yes, the problem is from the DOUBLE type (returned by the exponentiation function): viewtopic.php?p=243110#p243110
Other example:

Code: Select all

? bin(2^54)                     '' OK
? bin(2^54 - 1)                 '' NOK
? bin(cast(longint, 2^54 - 1))  '' NOK
? bin(cast(longint, 2^54) - 1)  '' OK

sleep

Code: Select all

1000000000000000000000000000000000000000000000000000000
1000000000000000000000000000000000000000000000000000000
1000000000000000000000000000000000000000000000000000000
111111111111111111111111111111111111111111111111111111
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: Bin won't display more than 53 bits?

Post by Tourist Trap »

@dodicat, fxm

yes I get it now. The last time I played with bin, I used strings and binary explicit numbers (&b010101...).

I think that BIN is in general to be used with strings, and valint and so on. A version of bin that would take advantage of powers of 2 would be interesting but I find it difficult to craft.
badidea wrote:Not sure what you are trying to build, but 'asm bsr' (bit scan reverse) is practically log2 for integers.
Just playing with bits. Thanks for the tip, I'll try to use it.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Bin won't display more than 53 bits?

Post by jj2007 »

badidea wrote:'asm bsr' (bit scan reverse) is practically log2 for integers.
Only under ideal conditions:

Code: Select all

  m2m ebx, 1
  PrintLine "ebx", Tb$, "bsr(ebx)" 
  For_ ct=0 To 9
	bsr ecx, ebx
	PrintLine Str$("%i\t", ebx), Str$(ecx)
	shl ebx, 1	; double ebx
	; add ebx, 7	; add some noise
  Next 

Code: Select all

ebx     bsr(ebx)
1       0
2       1
4       2
8       3
16      4
32      5
64      6
128     7
256     8
512     9
With "added noise":

Code: Select all

ebx     bsr(ebx)
1       0
9       3
25      4
57      5
121     6
249     7
505     8
1017    9
2041    10
4089    11
Post Reply