tags:

views:

691

answers:

12

How in Java do you return the first digit of an integer.?

i.e.

345

Returns an int of 3.

+25  A: 

The easiest way would be to use String.valueOf(Math.abs((long)x)).charAt(0) - that will give it you as a char1. To get that as an integer value, you could just subtract '0' (as in Unicode, '0' to '9' are contiguous).

It's somewhat wasteful, of course. An alternative would just be to take the absolute value, then loop round dividing by 10 until the number is in the range 0-9. If this is homework, that's the answer I'd give. However, I'm not going to provide the code for it because I think it might be homework. However, if you provide comments and edit your answer to explain how you're doing and what problems you're running into, we may be able to help.


1One sticky point to note is that the absolute value of Integer.MIN_VALUE can't be represented as an int - so you may should first convert to a long, then use Math.abs, then do arithmetic. That's why there's a cast there.

Jon Skeet
I don't like that this solution involves the conversion of an number to a string, but I do like the fact that its a oneliner, you got my vote.
monksy
That's going to be about '0' out. Doesn't work for Integer.MIN_VALUE.
Tom Hawtin - tackline
(1String.valueOf(-Math.abs(x)).charAt(1)` ? Or is that a bit obscure?)
Tom Hawtin - tackline
@Tom: I was just in the middle of editing for the Integer.MIN_VALUE issue. Working with longs makes it easier :) Not sure what you mean about it being '0' out though, given the second sentence of my first paragraph. It's not obvious whether the OP wants a character or an integer.
Jon Skeet
@Downvoter: Which bit?
Jon Skeet
@Jon Skeet: You start off with "The easiest way" and then proceed to agglomerate 4 functions and 2 casts with instructions for further processing. It's not a bad solution per se but I cannot agree with the ridiculous number of upvotes you're getting for this byzantine contraption.
Carl Smotricz
@Carl: There's only a single cast (to `long`) there, and three method calls (`valueOf`, `abs`, `charAt`). The looping suggestion in the second form would still require a cast (or implicit conversion) and `abs` to cope with `Integer.MIN_VALUE`. I don't agree that it's byzantine, either - it seems perfectly natural to me. An integer really only has a "first digit" when you consider it in a formatted sense - so converting it to string and taking the first character is pretty obvious, isn't it? The other complexities are just due to coping with negative numbers.
Jon Skeet
@Jon Skeet: I miscounted casts, and the voters are obviously on your side.
Carl Smotricz
@Carl: That doesn't make the voters right, of course :) I certainly wouldn't want to put you off from criticising... which isn't the same as promising I won't defend my solutions :) (How many negatives can I get into a sentence?)
Jon Skeet
@Jon: That depends: How many function calls can you get into one line? ;) But seriously, I think you're working far too hard to catch corner cases in a poorly specified homework assignment. Still, it's a correct solution, so if you edit your answer I'll retract my vote.
Carl Smotricz
Another jab at your solution, though: It's wholly inappropriate as the solution to a homework problem. How is he ever going to explain that code to his teacher? ;)
Carl Smotricz
@Carl: Edited. Getting it working at all was for the OP. Working out the corner cases was for me :)
Jon Skeet
The other thing that you could do, assuming that we don't care about objects being created is `String.valueOf(BigInteger.valueOf(x).abs()).charAt(0)`
Paul Wagland
A: 

Homework Hint: Convert it to a string and and return the first character.

George
.. which won't work on negative ints, supposedly :)
AdrianoKF
So grab the absolute value, then cast it to a string, then return the first character.
George
Too late - too many solutions already escaped ;)
Andreas_D
+8  A: 
public static int firstDigit(int n) {
  while (n < -9 || 9 < n) n /= 10;
  return Math.abs(n);
}

Should handle negative numbers pretty well, too. Will return a negative first digit in that case.

Carl Smotricz
String generalSolution = carlsSolution.replace("345", "Math.abs(inputValue))";
Andreas_D
This is wrong, i*i > 81 should be replaced by i >= 10
Gennadiy
@Andreas_D: I just realized I may have been missing votes because people couldn't make that intellectual leap, so I made an explicit function of it.
Carl Smotricz
@Gennadiy, I'm sorry I edited my solution since you made your comment, but it wasn't wrong before either. Any integer value whose square is greater than 81 has an absolute value greater than 9, and since it's an integer that means it's at least 10.
Carl Smotricz
`return Math.abs(n);`?
Tom Hawtin - tackline
@Tom: The spec doesn't say what to do with negative numbers. Are negative inputs allowed? Do they literally want the first *digit* or do they want the first *character* ( `-` ) ? I'm not willing to worry too hard about this.
Carl Smotricz
+6  A: 

Yet another way:

public int firstDigit(int x) {
  if (x == 0) return 0;
  x = Math.abs(x);
  return (int) Math.floor(x / Math.pow(10, Math.floor(Math.log10(x))));
}
liwp
I'd be interesting to know whether that works correctly for every integer. I'd be concerned about floating point inaccuracies creeping in - but it may be okay. Hard to test efficiently...
Jon Skeet
Interestingly enough, this solution yields the same result as mine for all integers between 0 and 100,000,000. However, it doesn't do negatives.
Carl Smotricz
What the hell, it's a correct solution. +1.
Carl Smotricz
Needs slight alterations to return 0 if x == 0 and firstDigit(-x) if x < 0.
lins314159
@lins314159: thanks, I added checks for those@Jon: I thought I'd test the algo with haskell's QuickCheck library and the results are interesting: when I run the test interactively it passes, when I compile the test code it fails at -1000, 1000. It turns out that log 1000 returns 2.999... in the compiled code, rather than 3. This is exactly the kind of floating point error you were worried about. This does not seem to happen in Java though (at least not with the same values). I'll see what the haskell mailinglist has to say.
liwp
+2  A: 
public static int getFirstDigit(int i) {
    while (Math.abs(i) >= 10 ) {
        i = i / 10;
    }
    return Math.abs(i);
}
Matthew Flynn
+1  A: 
int main(void) {
  int num = 3421;

  while (num*num + 10 - num*(1 + num) <= 0) {
    num *= (num - 0.9*num)/num;
  }

  std::cout << num << std::endl;
}
Chip Uni
+2  A: 

Fastest way would be :

  • Compute log of the abs(x), then get floor. Let's call it n.
  • Divide the number with 10^n
fastcodejava
How certain are you that computing a log and computing a power and then dividing once will be faster than performing up to 9 integer divisions by 10? I wouldn't like to guess that, to be honest... or claim it to be universally true across all processors and JVMs.
Jon Skeet
I'm rather shocked about this, but it turns out that liwp's solution, which is very similar to this, returns the correct result over most of its range (I gave up after 100 million). Is that luck or are those transcendental functions very amenable to this exact problem, or what?? To be fair, +1 here too.
Carl Smotricz
As for performance... yeah. They probably won't run this algorithm at any supercomputing centers. Does it matter? ;)
Carl Smotricz
+4  A: 

The missing recursive solution:

int getFirstInt(int input) {
  if (input > 0 ? input < 10 : input > -10) {
    return input > 0 ? input : -input;
  }
  return getFirstInt(input / 10);
}

I wouldn't use the ternary operator in real life but - isn't it kind of beautiful? ;)

Andreas_D
Doesn't cope with Integer.MIN_VALUE, but nice to see the recursive version. I don't think I'd use the conditional operator for the `if` condition, but I might use it for the return statement - at least if Math.abs didn't exist.
Jon Skeet
@Jon, tested it with Integer.MIN_VALUE before, and the result was '2', with and without casting to long... Is it really a problem?
Andreas_D
It won't be a problem since you never try to negate MIN_VALUE, but only ever try to negate values between -1 and -9, these (obviously) have positive equivalents.
Paul Wagland
A: 

This is Groovy, but it should be easy to convert to Java:

int firstNum(int x) {
    a = Math.abs(x)
    sig = Math.floor(Math.log10(a))
    return a / Math.pow(10, sig)
}

Results:

groovy> println(firstNum(345))
3

groovy> println(firstNum(3452))
3

groovy> println(firstNum(-112))
1

groovy> println(firstNum(9999))
9

groovy> println(firstNum(Integer.MAX_VALUE))
2

groovy> println(firstNum(Integer.MIN_VALUE + 1))
2

matt b
A: 

Adjusting my previous answer to handle Integer.MIN_VALUE and keep the cast to long out of the interation:

public static int getFirstDigit(int i) {
if (Math.abs((long)i) >= 10 ) {
    i = i / 10;
    while (Math.abs(i) >= 10 ) {
        i = i / 10;
    }
}
return Math.abs(i);

}

Matthew Flynn
A: 

Ignoring negative values leads to:

(""+345).charAt(0);
stacker
A: 
int a = 354;
int b = (int)(a / Math.Pow(10, (int)Math.Log10(a))); // 3
Terje
if the number is negative, Math.Abs() it first, naturally.
Terje