How can I only store non-zero digits from an integer?

I am currently using the following code, which removes all digits equal to zero from an integer.

int removeZeros(int candid) { int output = 0; string s(itoa(candid)); for (int i = s.size(); i != 0; --i) { if (s[i] != '0') output = output * 10 + atoi(s[i]); } return output; } 

Expected yield, for example. 102304 will be 1234.

Is there a more compact way to do this using an integer-working , i.e. non-string representation ? Will it really be faster?

+6
source share
7 answers

You can try something like this:

 template<typename T> T nozeros( T const & z ) { return z==0 ? 0 : (z%10?10:1)*nozeros(z/10)+(z%10); } 

If you want to do your processing one more step, you can do a good tail recursion, no need to use a helper function:

 template<typename T> inline T pow10(T p, T res=1) { return p==0 ? res : pow10(--p,res*10); } template<typename T> T nozeros( T const & z , T const & r=0, T const & zp =0) { static int digit =-1; return not ( z ^ r ) ? digit=-1, zp : nozeros(z/10,z%10, r ? r*pow10(++digit)+zp : zp); } 

Here's how it will work with input 32040

Ret, z, r, zp, numbers

-, 32040,0,0, -1

-, 3204,0,0, -1

-, 320,4,0,0, -1

-, 32,0,4,4, 0

-, 3,2,4, 0

-, 0.3.24, 1

-, 0,0,324, 2

324, -, -, -, -1

Integer calculations are always faster than actually converting integers to a string, comparing strings and finding strings to return them to integers.

The most interesting thing is that if you try to pass floats, you get good compile-time errors.

I argue that this is slightly faster than other solutions, as it makes less conditional estimates that will allow you to behave better with CPU branch prediction.

+1
source

Here is a way to do this without strings and buffers.

I tested this with only positive numbers. To do this work with negative numbers, this is an exercise left to you.

 int removeZeros(int x) { int result = 0; int multiplier = 1; while (x > 0) { int digit = x % 10; if (digit != 0) { int val = digit * multiplier; result += val; multiplier *= 10; } x = x / 10; } return result; } 
+6
source

Regarding maintainability, I would suggest that you don’t work directly with a numerical value. You can express your requirements in a very simple way using string manipulations, and although it is true that it is more likely to work slower than numerical manipulations, I expect you to be fast enough so you don't have to worry about performance if this is not an extremely tight loop.

 int removeZeros(int n) { auto s = std::to_string(n); s.erase(std::remove(s.begin(), s.end(), '0'), s.end()); return std::stoi(s); } 

As a bonus, this simple implementation correctly processes negative numbers. For zero, it throws std::invalid_argument , since removing all zeros from 0 does not result in a number.

+6
source

The string representation is not used here. However, I can not say anything about speed.

 int removezeroes(int candid) { int x, y = 0, n = 0; // I did this to reverse the number as my next loop // reverses the number while removing zeroes. while (candid>0) { x = candid%10; n = n *10 + x; candid /=10; } candid = n; while (candid>0) { x = candid%10; if (x != 0) y = y*10 + x; candid /=10; } return y; } 
+1
source

If C ++ 11 , I like it with the lambda function:

 int removeZeros(int candid){ std::string s=std::to_string(candid); std::string output; std::for_each(s.begin(), s.end(), [&](char& c){ if (c != '0') output += c;}); return std::stoi(output); } 
+1
source
 int number = 9042100; stringstream strm; strm << number; string str = strm.str(); str.erase(remove(str.begin(), str.end(), '0'), str.end()); number = atoi(str.c_str()); 
+1
source

Fixed implementation of g24l recursive solution:

 template<typename T> T nozeros(T const & z) { if (z == 0) return 0; if (z % 10 == 0) return nozeros(z / 10); else return (z % 10) + ( nozeros(z / 10) * 10); } 
0
source

All Articles