简体   繁体   中英

Find first digit of a number using ONLY integer operations

I can't understand how to solve the problem that the teacher gave me.

Given a number N (0 <= N <= 100), find its first digit.

For example:

input: 100
result: 1

input: 46
result: 4

input: 3
result: 3

It seemed easy at first, but (as the teacher said) it should be done using ONLY integer data types (in other words, using + , - , * , / and % operators). Is it even possible to do it this way?

I just can't realize how to extract the first digit from a variable-length number without using things like log10, conditions, "while" loop or string conversion.

Without any conditionals:

int H= N / 100;       // Hundreds digit
int T= (N / 10) % 10; // Tens digit
int U= N % 10;        // Units digit

int h= H;                      // Hundreds flag
int t= (T + 9) / 10 * (1 - h); // Tens flag
int u= (1 - t) * (1 - h);      // Units flag

int Answer= u * U + t * T + h * H; // Combination

Edit: Now tested for 0 and 100:

var result = n / 10 * (1 - n / 100) + n / 100 + (109 - n) / 100 * n;

How it works:

n        | n / 10 * (1 - n / 100) | n / 100 | (109 - n) / 100 * n
-----------------------------------------------------------------
10 - 99  | 1 - 9                  | 0       | 0
-----------------------------------------------------------------
100      | 0                      | 1       | 0
-----------------------------------------------------------------
0 - 9    | 0                      | 0       | 0 - 9

Use a while loop, and keep dividing the input number by 10, so long as we are starting with a value which is greater than or equal to 10. When the modified input is less than ten, then it means we have stripped off all digits to the right, except for the "first" digit.

int input = 100;

while (input >= 10)
{
    input /= 10;
}

Console.WriteLine("First digit is: {0}", input);

Demo

This is a non-generic response, and only works because the domain is limited. The idea is to return all the digits (hundred's, ten's, and one's) smooshed together." Some thoughts on specific ranges of numbers:

100 is easy because the ten's and one's units are both zero. There are no other three digit numbers, which is good, because anything with a non-zero one's or ten's place will cause problems below.

All numbers less than 100 can include the hundred's digit in the response because it will always be zero.

Any multiple of 10 is easy, just include the each hundred's ten's and one's value, because the other digits are zero.

The tricky part is the one's place. There needs to be a way to "cancel out" this value if a larger digit is supposed to be returned. For example, 87, we want the 8 but want to cancel out the 7.

This leads to the idea

(ten - 9)*(ten - 8)*(ten - 7)*(ten - 6)*(ten - 5)*(ten - 4)*(ten - 3)*(ten - 2)*(ten - 1)

What happens is that any time the ten's place is non-zero, the above will evaluate to zero. So we can multiply the one's place by this to zero out the one's place when the ten's place is non-zero. However, there's a problem when the ten's place is zero. In that case, we're off by a factor of 9! (nine factorial = 362880) and the wrong sign. This is why an extra minus sign is included, and divide out by 362880 to get the right answer when ten's place is zero.

public int GetFirstDigit(int n)
{
    var hundred = (n % 1000) / 100;
    var ten = (n % 100) / 10;
    var one = n % 10;

    return hundred + ten + one*
    (
    -(ten - 9)*(ten - 8)*(ten - 7)*(ten - 6)*(ten - 5)*(ten - 4)*(ten - 3)*(ten - 2)*(ten - 1)
    ) / 362880
    ;
}

check with

Enumerable.Range(0, 101).ToList().ForEach(x => Console.WriteLine(x + ": " + GetFirstDigit(x)));
static int Result(int input)
{
    return input/100 + (input%100/input)*input/10 + (input%10/input)*input;
}
  • input/100 will return 1 if and only if input equals 100, else 0
  • (input%100/input) will return 1 if and only if input < 100 , else 0
    • if input is lower than 10, input/10 will be 0
  • (input%10/input) will return 1 if and only if input < 10 , else 0

Caution

This would break if input == 0 , see @quanik's answer to handle 0.

However, it will work for 1-999.

I tried to solve the case but without success, I can only achieve finding the first digit if the N is 1 - 100. Here is my source code for it. Hope it helps https://dotnetfiddle.net/6XyOfd

if (N < 10)
  Output(N)
else if (N < 100)
  Output(N / 10)
else
  Output(1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM