Decimal to Binary Script
[1/6] from: ptretter::charter::net at: 1-Aug-2000 7:48
Ok, I created my first useful function. I created the following function
because enbase/base value 2 gave me a limitation. So add this script to
your %user.r file. Wish this could be added to /Core as it really needs a
simple function for this. I hope to post a view based Subnet Calculator
soon. Let me know if it helps.
Paul Tretter
dec-to-bin: func[
"Converts Based 10 Integers to Binary"
dn [integer!] "Base 10 Integer"][
holder: copy ""
while [dn / 2 <> 0][
either dn // 2 > 0 [insert holder 1][insert holder 0]
dn: to-integer dn / 2
]
print holder
]
[2/6] from: joel:neely:fedex at: 1-Aug-2000 10:51
[ptretter--charter--net] wrote:
> Ok, I created my first useful function.
>
Congratulations! Good feeling, isn't it? I always get psyched when I
get my head around a tool well enough to actually do something with it.
> I created the following function
> because enbase/base value 2 gave me a limitation. So add this script to
<<quoted lines omitted: 12>>
> print holder
> ]
Can I make a couple of suggestions?
1) As written, the function doesn't convert "integers", but only
positive integers. For example:
>> dec-to-bin -1
0
>> dec-to-bin -10
0000
>> dec-to-bin 0
>>
Handling these cases will make the function more general.
2) Since "holder" is not declared local, it shows up in the global
context. This is A Bad Idea. If there was already a variable
or function named "holder", invoking dec-to-bin would clobber it!
3) Instead of printing the result, why not simply return it? If
the result is returned to an interactive session, it will be
printed anyway. However, making the result available for further
processing allows for more general use. For example, how many
bits does it take to hold 4508321? (see below)
4) Avoid unnecessary tests whenever possible. In the line of code
> either dn // 2 > 0 [insert holder 1][insert holder 0]
notice that the expression dn // 2 returns 0 or 1 (for natural
dn, but see below), therefore this line can be shortened to
> insert holder dn // 2
With all of these suggestions implemented, the function looks like
this (the name change was simply so that I could have both defined
at once...)
dec2bin: func[
"Converts Based 10 Integers to Binary"
dn [integer!] "Base 10 Integer"
/local holder "accumulate non-zero results"
][
either dn = 0 [
"0"
][
either dn < 0 [
holder: next copy "-"
dn: - dn
][
holder: copy ""
]
while [dn > 0][
insert holder dn // 2
dn: to-integer dn / 2
]
head holder
]
]
And, to check the suggestions...
>> dec2bin 0
== "0"
>> dec2bin -1
== "-1"
>> dec2bin -10
== "-1010"
>> dec2bin 4508321
== "10001001100101010100001"
This last case (from point 3) reminds me to do
>> length? dec2bin 4508321
== 23
About the open issue from point 4, don't bother to read the rest of this if
you don't care about the mathematics -- the suggested implementation in
dec2bin avoids signed integer arithmetic and is therefore immune from the
problem discussed below.
-jn-
REBOL (unfortunately, in my opinion) interprets "to-integer" as
"the integer part as written out in text",
rather than the more mathematically correct
"largest integer not exceeding"
(and REBOL is not alone in this). What this means is that we get
>> -5 // 2
== -2.5
>> to-integer -5 / 2
== -2
Now, based on the definition of remainder, / and // MUST satisfy (for
integral a and b)
a = b * (to-integer a / b) + (a // b)
which backs us into the weird case that
>> -5 // 2
== -1
Why is this weird? There's lots of useful mathematics (and several
useful programming techniques, as well) based on the idea that the
modulus (remainder after division) is ALWAYS bounded between zero
and (divisor - 1). For example, think about "clock arithmetic"
using a 24-hour clock (in which the hours run from 0 to 23). To
get the hour that is thirteen hours after four in the afternoon,
just evaluate
>> (4 + 12 + 13) // 24
== 5
that is, 4 (o'clock) + 12 (i.e. PM) + 13 (elapsed time).
BUT... If I want to find out what hour is seventeen hours before
three in the morning, I get a problem...
>> (3 - 17) // 24
== -14
which ISN'T on the clock. We can sidestep this ugliness by either
1) making sure that we never try to take a remainder with negative
arguments (which is the approach taken in dec2bin above), or
2) write a helper function that cleans up the positive/negative
mess, as follows
mod: func [
"computes true (positive) modulus"
a [integer!] "dividend"
b [integer!] "divisor"
][
a // b + b // b
]
which allows us to see that
>> mod -5 2
== 1
>> mod -5 3
== 1
and solve the time problems above
>> mod (4 + 12 + 13) 24
== 5
>> mod (3 - 17) 24
== 10
Have fun!
[3/6] from: tim:johnsons-web at: 1-Aug-2000 7:56
That's cool Paul.
BTW: If you check out the user's guide, you'll
see the function print-binary in the section
on logical operators.
It does the same thing, but I as a relative
newbie find yours more readable. Might
be fun to compare benchmarks.
hmmm!
-Tim
At 07:48 AM 8/1/00 -0500, you wrote:
[4/6] from: ptretter:charter at: 1-Aug-2000 11:18
This is excellent stuff and I will be absorbing everything you have done. I
knew it didnt correctly handle negative integers and I also knew that it
would clobber "holder". Your suggestions are excellent and I appreciate
your comments. I originally made this to supplement a Subnet Calculator
that I was working on which my function was sufficient. I like your
modifications and explaination. Thanks for all the feedback.
Paul Tretter
[5/6] from: ptretter:charter at: 1-Aug-2000 11:19
I believe the one your referring to used the enbase function which is
limited in handling "0-255" to binary.
[6/6] from: tim:johnsons-web at: 1-Aug-2000 9:07
I would also suggest:
Add a refinement to pad with leading
zeroes if necessary:
I.E. dec2bin/32 0
>> 00000000000000000000000000000000
Really looks unnecessary, but useful
when illustrating a variable that is of type
integer! and has 32 bits. More of interest
in a teaching situation, which rebol can
be well suited to.
-Tim
At 10:51 AM 8/1/00 -0500, you wrote:
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted