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:
>[EMAIL PROTECTED] 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
>> 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
>>
>> ]
>
>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!
>
>