From: pete on
On Jun 30, 3:25 pm, Ken Snyder <kendsny...(a)gmail.com> wrote:

I must be missing something. What is that subtle something?

> (5).toString(2);  // "101"
> (16).toString(2); // "10000"

As I read it, the OP wants to go FROM string, not toString( ). Thus:

function toBin(n) {
return + n;
}

straight from the FAQ, should work, should it not?
[ http://www.jibbering.com/faq/notes/type-conversion/#tcParse ]

-- pete

From: pete on
On Jul 1, 5:11 am, pete <pete...(a)yahoo.com> wrote:

> I must be missing something. What is that subtle something?

Answering my own question, that "subtle something" is:

> real code works with integer strings of any length

as the OP specified early, whereas my suggested solution ( binVal = +
stringVal ) only works for strings of max 10 digits, and fewer than
half of those. Sorry for missing the OP's crucial stipulation.

-- pete
From: Scott Sauyet on
On Jun 30, 11:12 am, RobG <rg...(a)iinet.net.au> wrote:
> I'm working on a function to convert decimal integers to binary. The
> version below is an example of my implementation of a halving
> algorithm, real code works with integer strings of any length and
> handles sign. I've reduced the functionality a bit so I don't have to
> post the supporting functions for large ints.
>
> This one only works within the range of values supported by the
> ECMAScript implementation it's running in and with unsigned integers
> (don't use numbers larger than 9 digits).

This version works with arbitrary length ints, that is on strings
containing nothing but decimal digits:

var toBin = (function() {
var digitHalves = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4],
remainderHalves = [5, 5, 6, 6, 7, 7, 8, 8, 9, 9];
return function(digits) {
digits = digits.split("");
var binDigits = [];
while (digits.length) {
var ptr = 0, digit = 0;
while (digits[0] == '0') digits.shift();
while (ptr < digits.length) {
var carry = digit
digit = digits[ptr] % 2;
digits[ptr] = carry ? remainderHalves[digits[ptr]]
: digitHalves[digits[ptr]];
ptr++;
}
binDigits.push(digit);
}
binDigits.reverse().shift();
return binDigits.join("");;
};
}());

I have not tested performance. It's performing division digit-by-
digit, via lookups, so I wouldn't be surprised if it's slow. But it
seems to be straightforward. The two lookups, digitHalves and
remainderHalves respectively return half of the current digit and half
of ten more than the current digit, in either case rounded down to the
nearest digit. It does avoid a division...

--
Scott
From: Stefan Weiss on
On 01/07/10 18:44, Scott Sauyet wrote:
> On Jun 30, 11:12 am, RobG <rg...(a)iinet.net.au> wrote:
>> I'm working on a function to convert decimal integers to binary. The
>> version below is an example of my implementation of a halving
>> algorithm, real code works with integer strings of any length and
>> handles sign. I've reduced the functionality a bit so I don't have to
>> post the supporting functions for large ints.
>>
>> This one only works within the range of values supported by the
>> ECMAScript implementation it's running in and with unsigned integers
>> (don't use numbers larger than 9 digits).

I didn't quite understand the point of your function.
Either you're doing arbitrary precision math, which means you can't
treat the input string as a number
- or -
you're restricting yourself to integers in the usual supported range,
which means you can perform normal math operations on the string, but
then you could just as well just use toString(2).

> This version works with arbitrary length ints, that is on strings
> containing nothing but decimal digits:

Damn, beat me to it :)

> var toBin = (function() {
> var digitHalves = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4],
> remainderHalves = [5, 5, 6, 6, 7, 7, 8, 8, 9, 9];
> return function(digits) {
> digits = digits.split("");
> var binDigits = [];
> while (digits.length) {
> var ptr = 0, digit = 0;
> while (digits[0] == '0') digits.shift();
> while (ptr < digits.length) {
> var carry = digit
> digit = digits[ptr] % 2;
> digits[ptr] = carry ? remainderHalves[digits[ptr]]
> : digitHalves[digits[ptr]];
> ptr++;
> }
> binDigits.push(digit);
> }
> binDigits.reverse().shift();
> return binDigits.join("");;
> };
> }());
>
> I have not tested performance. It's performing division digit-by-
> digit, via lookups, so I wouldn't be surprised if it's slow. But it
> seems to be straightforward. The two lookups, digitHalves and
> remainderHalves respectively return half of the current digit and half
> of ten more than the current digit, in either case rounded down to the
> nearest digit. It does avoid a division...

Interesting, I didn't think of that.

Here's my attempt:

function toBin (numStr) {
var bigInt = numStr.split(""),
len = bigInt.length,
result = [],
rem, digit, i;
do {
for (rem = i = 0; i < len; ++i) {
digit = +bigInt[i] + rem * 10,
rem = digit & 1,
bigInt[i] = (digit - rem) / 2; // or (digit / 2) | 0
}
if (!bigInt[0]) {
bigInt.shift();
--len;
}
result.push(rem);
} while (len);
return result.reverse().join("");
}

It's a pretty naive implementation of a normal short division. I'm sure
there are more efficient ways to do it, but I thought looking them up
would be cheating.

Performance appears more or less comparable. The only difference in the
results I've seen is that yours returns an empty string for "0" ;-)


--
stefan
From: Stefan Weiss on
On 01/07/10 19:34, Stefan Weiss wrote:
> digit = +bigInt[i] + rem * 10,
> rem = digit & 1,
> bigInt[i] = (digit - rem) / 2; // or (digit / 2) | 0

Whoops, those were suposed to be statements. I must have missed that
during refactoring.


--
stefan