Jump to content

[SOLVED] Bitwise, base-2 categorization system acting oddly.


Goldeneye

Recommended Posts

Well, I fixed the problem I made a topic about 3 days ago.

 

My new problem is with the category-numbers themselves. The way it works is that I take an array of category-names and run them through a function which generates a Base-2 number for each name and puts them in a key => value array.

 

Example:

<?php
$_file_type = array('Applications', 'Audio', 'Video', 'Images', 'Scripts', 'Documents', 'Miscellaneous');
function generate($array){
	$n = count($array);
	$c = array();
	for($i = 0; $i < $n; ++$i)
		$c[pow(2, $i)] = $array[$i];
	return $c;
}
?>

 

So the returned array would be array(1 => 'Applications', 2 => 'Audio', 4 => 'Video', 8 => 'Images', 16 => 'Scripts', 32 => 'Documents', 64 => 'Miscellaneous');

 

My function works well up till a certain number of array-elements. The 32nd array-element/exponent produces a negative-number (-2147483648), and then every array-element after the 32nd array-element  simply produces 0.

 

Does anyone know why this happens? Can it be "fixed"?

My function works well up till a certain number of array-elements. The 32nd array-element/exponent produces a negative-number (-2147483648), and then every array-element after the 32nd array-element  simply produces 0.

 

Not on a 32-bit system, no. You'd have to use a version of PHP compiled for 64-bit on a machine and operating system that supports it. Even then you would just hit the barrier only a little higher.

My function works well up till a certain number of array-elements. The 32nd array-element/exponent produces a negative-number (-2147483648), and then every array-element after the 32nd array-element  simply produces 0.

 

Not on a 32-bit system, no. You'd have to use a version of PHP compiled for 64-bit on a machine and operating system that supports it. Even then you would just hit the barrier only a little higher.

 

Thanks Daniel0! Unfortunately, I don't have that option. I have found another solution though -- it turns out that array-keys cannot hold floating-number-points (or scientific notation).

 

The problem is that PHP natively uses floating-number-points to display very large numbers.

Example: pow(2, 43) = 8.79609302221E+012.

 

When you try to assign this as an array-key, you will receive a "bad" number such as 0 or a negative integer.

 

The solution is to convert that floating-point-number to its decimal-equivalent. In this case, the decimal-equivalent to 8.79609302221E+012 is 8796093022210.

 

How do you convert a floating-point-number to a decimal-number? You have to write a function to do this because (at the time of this writing) I believe PHP doesn't have a function for such an operation. I have found a function that does do this that was written by someone named Bob. It can be found at http://ca2.php.net/float

Why are you storing things like that in the first place?

 

Anyways, seeing as using a string is a good enough compromise for you, you can just use bcpow.

 

daniel@daniel-laptop:~$ php -r "echo bcpow("2", "1000") . PHP_EOL;"
10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

Why are you storing things like that in the first place?

 

Anyways, seeing as using a string is a good enough compromise for you, you can just use bcpow.

 

daniel@daniel-laptop:~$ php -r "echo bcpow("2", "1000") . PHP_EOL;"
10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

 

It's just the way I decided to write my categorization-system. There are probably better ways of doing a large-categorization system. I chose it to do this way because I wanted to stay away from using an SQL-based system. I decided a base-2 system that works with bitwise operators was e a better choice (more efficient for a smaller number of categories -- which is what I had in mind when I first created this categorization-system).

 

I didn't know about that function. I'll give it a try as well -- it'll be a lot more efficient since it is a native function. I tried the gmp_pow function but I don't have the GMP-Library installed.

I suppose I just don't see the point in using only powers of 2. I don't really see why you couldn't use a regular enumerated array.

 

Oh yeah (and I know this might be seen as nitpicking), but it's still base 10. Base 2 is just using only two distinct digits that are raised to a power of 2. Effectively, (9)10 = (1001)2. You're not using base 10 only when using the numbers 1, 10, 100, 1000 etc. either. Of course the numbers are always stored internally in base 2 because that makes the circuits easier to make. Given any number in any base, you can always convert it to base b for some integer b > 1 (also called doing a base b expansion). Just wanted to get the nomenclature straight :)

I'm using base-2 because it's the only system I know of that works in the following way:

<?php
   $num = 7;
   if($num & 1) echo '$num is in category 1';
   if($num & 2) echo '$num is in category 2';
   if($num & 4) echo '$num is in category 3';
?>

 

I'm not sure if a regularly numerated system would work that way. It might, I just don't know how to utilize it in the same way as I did with my current system. I like the way my categorization-system is now because I can simply store $num in a single database-field it sounds silly but I don't like having to create multiple records in a separate database-table just for showing that my content has more than one category.

 

Thank you for that piece of enlightenment, Daniel0. :) Having taught myself from looking mostly at other people's scripts, I didn't read as many tutorials as I should've when I first started writing PHP-code so some of my technical terminology might be incorrect.

I suppose I would just store them in a tree like this:

<?php
$tree = array(
    array(
        'name' => 'Category 1',
        'children' => array(
            array(
                'name' => 'Child 1',
                'children' => array(),
            ),
            array(
                'name' => 'Child 2',
                'children' => array(),
            ),
        ),
    ),
    array(
        'name' => 'Category 2',
        'children' => array(
            array(
                'name' => 'Child 3',
                'children' => array(
                    array(
                        'name' => 'Child 3-1',
                        'children' => array(),
                    ),
                ),
            ),
        ),
    ),
    array(
        'name' => 'Category 3',
        'children' => array(),
    ),
);

 

Writing it out it would look something like this:

 

Category 1

--Child 1

--Child 2

Category 2

--Child 3

----Child 3-1

Category 3

 

That would also support infinite depth (though still bounded by the computer's memory of course).

I suppose I would just store them in a tree like this:

<?php
$tree = array(
    array(
        'name' => 'Category 1',
        'children' => array(
            array(
                'name' => 'Child 1',
                'children' => array(),
            ),
            array(
                'name' => 'Child 2',
                'children' => array(),
            ),
        ),
    ),
    array(
        'name' => 'Category 2',
        'children' => array(
            array(
                'name' => 'Child 3',
                'children' => array(
                    array(
                        'name' => 'Child 3-1',
                        'children' => array(),
                    ),
                ),
            ),
        ),
    ),
    array(
        'name' => 'Category 3',
        'children' => array(),
    ),
);

 

Writing it out it would look something like this:

 

Category 1

--Child 1

--Child 2

Category 2

--Child 3

----Child 3-1

Category 3

 

That would also support infinite depth (though still bounded by the computer's memory of course).

 

Ohhh! Of course, now it's obvious. :P I think I'll start to work on utilizing that so I can use it in my current project as opposed to my current system. I remember trying that sort of system when I first started working with PHP but I was having a lot of trouble with looping through all of the dimensions without bloating the code. So I'll work on getting that going. You helped me exponentially (ha ha) more than I anticipated when I first created this topic. Arigato Gozaimasu!

 

Edit: I see you read my other topic about my looping problem from the above array-tree you provided. :P

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.