tags:

views:

262

answers:

7

Hello all,

Is this even at all possible?

How would I truncate zeros?

In the integer withOUT using any masking techniques (NOT ALLOWED: 0x15000000 & 0xff000000 like that.). And also WITHOUT any casting.

A: 

The easiest way is to convert the int to a byte, so you are now down to 8 bits, so not everything is truncated, necessarily, but it would have fewer zeroes.

I am hoping this isn't for homework, but because I fear it is, giving you all the code would not be fair.

James Black
This is out of my own interest.
RealHIFIDude
+4  A: 

Well, really, if you want to truncate the right side, the naive solution is:

uint input = 0x150000;
if(input)
{
    while(!(input & 0x01))  // Replace with while(!(input % 0x10)) if you are actually against masking.
    {
        input >>= 1;
    }
}

// input, here, will be 0x15.

Though, you can unroll this loop. As in:

if(!(input & 0xFFFF)) { input >>= 16; }
if(!(input & 0x00FF)) { input >>= 8;  }
if(!(input & 0x000F)) { input >>= 4;  }  // Comment this line, down, if you want to align on bytes.
if(!(input & 0x0003)) { input >>= 2;  }  // Likewise here, down, to align on nybbles.
if(!(input & 0x0001)) { input >>= 1;  }
John Gietzen
I would test for 0. Otherwise you may go into an infinite loop.
Martin York
indiv
Mmm.. technically that's a masking technique.
paxdiablo
@Martin, True. Though, I was in the midst of an edit saying that... @indiv, Very good. Updated.
John Gietzen
Souldn't you mask with 0xF and shift by 4 in your first example?
sellibitze
Only if he wanted to align on bytes. He said, 'zeros,' which implies 'digits.'
John Gietzen
He's showing numbers written in HEX and says he wants the trailing zeros removed. A HEX number ends in a zero if it is a multiple of 16. Being even is not sufficient for a trailing zero in HEX.
sellibitze
OK! FINE, Hence the Comment on how to ALIGN ON NYBLES! Sheesh.
John Gietzen
A: 

Shift right with 24. Make sure your variable is unsigned.

Mads Elvheim
And what about with 0x10?
GMan
Unfortunately, the input isn't always exactly a particular number of 00's . sometimes 4, sometimes 6, sometimes 2. How to trim without any predicting?
RealHIFIDude
The question didn't mention an arbitrary number of zeros. Badly phrased questions get stupid answers.
Mads Elvheim
+3  A: 

One way to do it without any masking (assuming you want to truncate zero bits):

int input = 0x150000;
while (input && !(input%2))
    input >>= 1;

Here's a complete program which illustrates it.

#include <stdio.h>

int main (int argc, char *argv[]) {
    int input = 0;
    if (argc < 2) {
        fprintf (stderr, "Needs at least one parameter.\n");
        return 1;
    }
    input = atoi (argv[1]);
    printf ("%x -> ", input);
    while (input && !(input%2))
        input >>= 1;
    printf ("%x\n",input);
    return 0;
}

If you want to truncate zero nybbles, use:

while (input && ((input%16)==0))
    input >>= 4;
paxdiablo
That is, of course, cheating. ;)
John Gietzen
Kobayashi Maru - sometimes the only way to win the game is to change the rules :-)
paxdiablo
I'd say that so far you're the only one that noticed that the question specified HEX and avoided any masking. +1
Tom
sbi
Oh, and what happens if I call your program like this: `pax_test blah`? (This question has a C++ tag, you know. Why not use streams?)
sbi
paxdiablo
@Pax: I'm really sorry if I offended you. I didn't mean to. I agree with your answer regarding the masking. That was a brainfart of mine. I disagree with your answer regarding `atoi`. IMO, using `atoi` leads to the dark side: `assert(atoi("0")!=atoi("blah"));` And having taught C++ for years - with some of the students later becoming fellow workers - I have learned the hard way that one should do it Right(TM) even in the smallest example.
sbi
No offence taken, @sbi, the medium we use doesn't always allow for full flow of communication. I don't usually rely on atoi except for quick and dirty stuff - in fact, part of my vast library of tools consists of a "better" atoi that checks the entire string is numeric. But if I were to worry about all those sort of things here on SO, my answers would become even *more* lengthy and incomprehensible :-)
paxdiablo
+2  A: 

John Gietzen's answer is my favourite, but for fun, it can actually be done without a loop!

If you know how many trailing zeros there are, then you can just shift right that number of bits. There are a number of techniques for finding the number of bits. See the few sections following the linear algorithm here: http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightLinear.

Martin
I have it without a loop at the bottom. ;) Nice link, though.
John Gietzen
+1  A: 

Divide by 16 (one nybble or hex digit's worth), as long as it's a multiple of 16:

if ( number )
    while ( number % 16 == 0 )
        number /= 16;

Of course, you can drop the initial test for zero if you know you'll never that as input.

Boojum
infinite loop for number==0
sellibitze
@sellibitze: Not so. The first line guards against that.
Boojum
Unless another thread comes in and changes it to 0 between the if and the while. Maybe we should mutex-protect the whole thing :-)
paxdiablo
+1  A: 

Does this count as masking?

unsigned int truncate(unsigned int input)
{
    while (input != 0 && input % 0x10 == 0)
    {
        input /= 0x10;
    }

    return input;
}
bobbymcr