Page 1 of 2

Bin2Dec() »»» Converting binary numbers to decimal system

Posted: Thu Jan 18, 2007 1:54 pm
by AND51
Hello!

This is just another nice competition. But I also request the procedures from this threads to be included into the next version of PB.
  • This a nice Bin2Dec() functin, converting even high numbers (returning value is a quad). This makes it possible to convert any BinQ()-values back to the decimal system. Even negative binary numbers are supported! Furthemore, you can use this procedure with Unicode.
My function can be reduced by 1 line, but unfortunately there is a bug regarding quads. Fred must fix this: http://www.purebasic.fr/english/viewtopic.php?t=25367

Code: Select all

Procedure.q Bin2Dec(binary.s)
	Protected result.q, n, temp
	For n=MemoryStringLength(@binary)-1 To 0 Step -1
		temp=(PeekC(@binary+n*SizeOf(Character))-48)*1<<(MemoryStringLength(@binary)-1-n)
		result+temp ; leave this line untouched, quad-bug otherwise!
	Next
	ProcedureReturn result
EndProcedure


Debug Bin(125)
Debug Bin2Dec(Bin(125))

@ Flype: You're welcome... :lol:
@ Anyone else: You, too! :wink:

Posted: Thu Jan 18, 2007 3:40 pm
by remi_meier
Now beat that:

Code: Select all

Procedure myBin2Dec(s.s, pos.l = 0, temp.l = 0, temp2.l = 0)
  ProcedureReturn (Len(s) And (1+PokeL(@temp2, (PeekC(@s+(Len(s)-1)*SizeOf(Character))-48)*(1<<pos)))) * temp2 + (Len(s) And (1+PokeL(@temp, myBin2Dec(Left(s, Len(s)-1), pos+1)))) * temp
EndProcedure
:D
ok, no quads, but I don't care about bugs. It should work with quads. :wink:

Posted: Thu Jan 18, 2007 3:44 pm
by ts-soft
@remi_meier
recursive, nice work :wink:

Posted: Thu Jan 18, 2007 3:48 pm
by AND51
Beeindruckend! :shock:

Very nice, but aren't you "cheating", when you define your variables as procedure-parameters?
I've never seen a PB procedure, doing so.

@ quads: In my opionion, quads are very important, so you shouldn't leave them out. If you're doing so, BinQ() does not make sense any longer...

Posted: Thu Jan 18, 2007 3:54 pm
by remi_meier
That's no cheating :P
But yes, don't use this procedure in any projects, it has no advantage
at all :wink:

Yes, quads are nice. I don't use them very often. And my code above
just crashes with quads -> I don't care...

Posted: Thu Jan 18, 2007 3:56 pm
by AND51
Now I understand you. However, your procedure remains impressively!
Now you can try to beat my "Hex2Dec()" :wink:

Posted: Thu Jan 18, 2007 4:03 pm
by remi_meier
No :wink:
I'll use my time for something else now.

Posted: Thu Jan 18, 2007 5:07 pm
by Trond
Much faster, but doesn't take negative numbers:

Code: Select all

Procedure.q Bin2Dec2(Hex.s)
  Protected Result.q
  Protected Char.l
  Ptr = @Hex
  Char = PeekC(Ptr) - '0'
  While Char <> - '0'
    Ptr + SizeOf(Character)
    Result = Result << 1 + Char
    Char = PeekC(Ptr) - '0'
  Wend
  ProcedureReturn Result
EndProcedure

Posted: Thu Jan 18, 2007 5:39 pm
by AND51
Nice, but you don't care about clean code, do you?
You don't protect 'ptr' and pay attention to 'EnableExplicit'.

Please, correct this, ok?

Code: Select all

Procedure.q Bin2Dec2(Hex.s) 
  Protected Result.q,Ptr = @Hex, Char.l=PeekC(Ptr) - '0'
  While Char <> - '0' 
    Ptr + SizeOf(Character) 
    Result = Result << 1 + Char 
    Char = PeekC(Ptr) - '0' 
  Wend 
  ProcedureReturn Result 
EndProcedure 


Debug Bin2Dec2("101")
Your performance is good!

Posted: Thu Jan 18, 2007 5:43 pm
by remi_meier
Actually, that's no clean code either:

Code: Select all

Protected Result.q,Ptr = @Hex, Char.l=PeekC(Ptr) - '0'
Readability does also count :!:
And your pointer isn't a pointer ;)
The Char isn't a char, etc :D

Posted: Thu Jan 18, 2007 5:49 pm
by AND51
OK, ther are too many spaces... I would code like that:

Code: Select all

Protected Result.q, Ptr=@Hex, Char.l=PeekC(Ptr)-'0'
This is clear enough for me. I already got used to this useful feature.

Since PB 4.00, you can directly write into variables while declaring them.

if you get used to this, maybe you'll agree to me.

Posted: Thu Jan 18, 2007 5:58 pm
by remi_meier
I am already used to it, but not for expressions like "PeekC(Ptr)-'0'". I
use it only with literal values like 1, 2, 666 or "Test". And mostly I even
split them in several lines.
You can't tell me that

Code: Select all

Protected Result.q, Ptr=@Hex, Char.l=PeekC(Ptr)-'0'
is more readable than

Code: Select all

Protected Result.q, *Ptr, Char.c

*Ptr = @Hex
Char = PeekC(*Ptr) - '0'
And you really should use the appropriate datatypes for each variable.

Posted: Thu Jan 18, 2007 6:11 pm
by Trond
I use only one declared variable per line, unless i have two related variables that does not need to be initialized and are of the same type.
* is for pointer to structures. I see no reason to use it on a long since the behaviour doesn't change. Also, *Ptr becomes a pointer to a pointer, which isn't right.

This is the cleanest code:

Code: Select all

Procedure.q Bin2Dec2(Hex.s) 
  Protected Result.q 
  Protected Char.l 
  Protected Ptr = @Hex 
  Char = PeekC(Ptr) - '0' 
  While Char <> - '0' 
    Ptr + SizeOf(Character) 
    Result = Result << 1 + Char 
    Char = PeekC(Ptr) - '0' 
  Wend 
  ProcedureReturn Result 
EndProcedure
That's really a mess:

Code: Select all

Protected Result.q,Ptr = @Hex, Char.l=PeekC(Ptr) - '0'
Multiple initializations on one line, no space after comma, no space around = operator and multiple types on one line.

Posted: Thu Jan 18, 2007 6:14 pm
by remi_meier
No, Trond :)
Ptr and *Ptr are not the same! They are the same, when you don't use
Define.f or something like that. *Ptr is just safer (Ptr.l would just be wrong).
*Ptr is not a pointer to a pointer, that's just possible through structures.

I accept your code, but mine is cleaner :P

Code: Select all

Procedure.l Bin2Dec(s.s)
  Protected *ptr.CHARACTER
  Protected pos.l, Value.l
  
  If s
    pos  = Len(s) - 1
    *ptr = @s
    
    While *ptr\c <> 0
      If *ptr\c = '1'
        Value + (1 << pos)
        
      ElseIf *ptr\c <> '0'
        Value = 0
        Break
        
      EndIf
      
      pos  - 1
      *ptr + SizeOf(CHARACTER)
    Wend
    
  EndIf
  
  ProcedureReturn Value
EndProcedure


Debug Bin2Dec(Bin(125))
(that's how I would write it in a project)

Posted: Fri Jan 19, 2007 1:16 am
by blueznl
clean is a matter of taste, i hate 'break' statements...

anyway, i just reenter the competition with the same code for hextodec :-)

http://www.purebasic.fr/english/viewtopic.php?t=25445

can we now do octals as well? :-)