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...
@ Anyone else: You, too!

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

ok, no quads, but I don't care about bugs. It should work with quads.

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

Posted: Thu Jan 18, 2007 3:48 pm
by AND51
Beeindruckend!
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
But yes, don't use this procedure in any projects, it has no advantage
at all
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()"

Posted: Thu Jan 18, 2007 4:03 pm
by remi_meier
No
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

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
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?
