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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 :)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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).

Link to comment
Share on other sites

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

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.