Related
I want to ask about what mistake I had make because i want to sum up the value in the odd position into Sumlast variable and the sum of even position value into Sumlastwo variable.
However I am required to double up the every value in even position then separate them into 2 digit like 9X2 = 18 ---> 1+8
For the odd value have no issue but when it reach the even position there is some issue.
Example I had did the input : 81
Output:
7
1
But when I type more digit like :9181
it become output:
27
2
it suppose to be (9X2) , (8X2) --> 18 , 16 = 1+8+1+6 = 16
output:
16
2
public static void main(String[] args) {
int c = 1;
int Sumlast = 0;
int Sumlasttwo = 0;
int numeven = 0;
Scanner myscanner = new Scanner(System.in);
System.out.print("Please enter your 8 digit number credit card: ");
String num = myscanner.nextLine();
if(num.length() != 8) //check the number of digit is 8
{
int test = Integer.parseInt(num);
while(test != 0)
{
if(c%2 == 0) //even
{
numeven = test * 2;
while(numeven > 0)
{
Sumlasttwo += (numeven%10);
numeven /= 10;
}
}
else //odd
{
Sumlast += test%10;
}
test /= 10;
c++;
}
System.out.println(Sumlasttwo);
System.out.println(Sumlast);
}
}
You forgot to take the digit from test in the even-case.
int test = Integer.parseInt(num);
while (test != 0)
{
int digit = test % 10;
if (c % 2 == 0) //even
{
int numeven = digit * 2;
while (numeven > 0)
{
Sumlasttwo += numeven % 10;
numeven /= 10;
}
}
else //odd
{
Sumlast += digit;
}
test /= 10;
c++;
}
Also it is more readable to declare numeven as near to its usage as possible.
Sumlast in java conventionally is written sumLast. Also } else { and ...) { is such a convention, but for instance not in C, and not as holy as camel-case names.
Debugging would have helped.
Using a help method would have made the code better:
boolean even = true;
while (test != 0) {
int digit = test % 10;
if (even) {
sumEven += digitsSum(digit * 2);
} else {
sumOdd += digit;
}
test /= 10;
even = !even;
}
private static void digitSum(int n) {
int sum = 0;
while (n > 0) {
sum += n % 10;
n /= 10;
}
return sum;
}
Can anyone explain to me how to reverse an integer without using array or String. I got this code from online, but not really understand why + input % 10 and divide again.
while (input != 0) {
reversedNum = reversedNum * 10 + input % 10;
input = input / 10;
}
And how to do use this sample code to reverse only odd number. Example I got this input 12345, then it will reverse the odd number to output 531.
Java reverse an int value - Principles
Modding (%) the input int by 10 will extract off the rightmost digit. example: (1234 % 10) = 4
Multiplying an integer by 10 will "push it left" exposing a zero to the right of that number, example: (5 * 10) = 50
Dividing an integer by 10 will remove the rightmost digit. (75 / 10) = 7
Java reverse an int value - Pseudocode:
a. Extract off the rightmost digit of your input number. (1234 % 10) = 4
b. Take that digit (4) and add it into a new reversedNum.
c. Multiply reversedNum by 10 (4 * 10) = 40, this exposes a zero to the right of your (4).
d. Divide the input by 10, (removing the rightmost digit). (1234 / 10) = 123
e. Repeat at step a with 123
Java reverse an int value - Working code
public int reverseInt(int input) {
long reversedNum = 0;
long input_long = input;
while (input_long != 0) {
reversedNum = reversedNum * 10 + input_long % 10;
input_long = input_long / 10;
}
if (reversedNum > Integer.MAX_VALUE || reversedNum < Integer.MIN_VALUE) {
throw new IllegalArgumentException();
}
return (int) reversedNum;
}
You will never do anything like this in the real work-world. However, the process by which you use to solve it without help is what separates people who can solve problems from the ones who want to, but can't unless they are spoon fed by nice people on the blogoblags.
I am not clear about your Odd number.
The way this code works is (it is not a Java specific algorithm)
Eg.
input =2345
first time in the while loop
rev=5 input=234
second time
rev=5*10+4=54 input=23
third time
rev=54*10+3 input=2
fourth time
rev=543*10+2 input=0
So the reversed number is 5432.
If you just want only the odd numbers in the reversed number then.
The code is:
while (input != 0) {
last_digit = input % 10;
if (last_digit % 2 != 0) {
reversedNum = reversedNum * 10 + last_digit;
}
input = input / 10;
}
Simply you can use this
public int getReverseInt(int value) {
int resultNumber = 0;
for (int i = value; i !=0; i /= 10) {
resultNumber = resultNumber * 10 + i % 10;
}
return resultNumber;
}
You can use this method with the given value which you want revers.
while (num != 0) {
rev = rev * 10 + num % 10;
num /= 10;
}
That is the solution I used for this problem, and it works fine.
More details:
num % 10
This statement will get you the last digit from the original number.
num /= 10
This statement will eliminate the last digit from the original number, and hence we are sure that while loop will terminate.
rev = rev * 10 + num % 10
Here rev*10 will shift the value by left and then add the last digit from the original.
If the original number was 1258, and in the middle of the run time we have rev = 85, num = 12 so:
num%10 = 2
rev*10 = 850
rev*10 + num%10 = 852
int aa=456;
int rev=Integer.parseInt(new StringBuilder(aa+"").reverse());
import java.util.Scanner;
public class Reverse_order_integer {
private static Scanner scan;
public static void main(String[] args) {
System.out.println("\t\t\tEnter Number which you want to reverse.\n");
scan = new Scanner(System.in);
int number = scan.nextInt();
int rev_number = reverse(number);
System.out.println("\t\t\tYour reverse Number is = \"" + rev_number
+ "\".\n");
}
private static int reverse(int number) {
int backup = number;
int count = 0;
while (number != 0) {
number = number / 10;
count++;
}
number = backup;
int sum = 0;
for (int i = count; i > 0; i--) {
int sum10 = 1;
int last = number % 10;
for (int j = 1; j < i; j++) {
sum10 = sum10 * 10;
}
sum = sum + (last * sum10);
number = number / 10;
}
return sum;
}
}
See to get the last digit of any number we divide it by 10 so we either achieve zero or a digit which is placed on last and when we do this continuously we get the whole number as an integer reversed.
int number=8989,last_num,sum=0;
while(number>0){
last_num=number%10; // this will give 8989%10=9
number/=10; // now we have 9 in last and now num/ by 10= 898
sum=sum*10+last_number; // sum=0*10+9=9;
}
// last_num=9. number= 898. sum=9
// last_num=8. number =89. sum=9*10+8= 98
// last_num=9. number=8. sum=98*10+9=989
// last_num=8. number=0. sum=989*10+8=9898
// hence completed
System.out.println("Reverse is"+sum);
public static void main(String args[]) {
int n = 0, res = 0, n1 = 0, rev = 0;
int sum = 0;
Scanner scan = new Scanner(System.in);
System.out.println("Please Enter No.: ");
n1 = scan.nextInt(); // String s1=String.valueOf(n1);
int len = (n1 == 0) ? 1 : (int) Math.log10(n1) + 1;
while (n1 > 0) {
rev = res * ((int) Math.pow(10, len));
res = n1 % 10;
n1 = n1 / 10;
// sum+=res; //sum=sum+res;
sum += rev;
len--;
}
// System.out.println("sum No: " + sum);
System.out.println("sum No: " + (sum + res));
}
This will return reverse of integer
Just to add on, in the hope to make the solution more complete.
The logic by #sheki already gave the correct way of reversing an integer in Java. If you assume the input you use and the result you get always fall within the range [-2147483648, 2147483647], you should be safe to use the codes by #sheki. Otherwise, it'll be a good practice to catch the exception.
Java 8 introduced the methods addExact, subtractExact, multiplyExact and toIntExact. These methods will throw ArithmeticException upon overflow. Therefore, you can use the below implementation to implement a clean and a bit safer method to reverse an integer. Generally we can use the mentioned methods to do mathematical calculation and explicitly handle overflow issue, which is always recommended if there's a possibility of overflow in the actual usage.
public int reverse(int x) {
int result = 0;
while (x != 0){
try {
result = Math.multiplyExact(result, 10);
result = Math.addExact(result, x % 10);
x /= 10;
} catch (ArithmeticException e) {
result = 0; // Exception handling
break;
}
}
return result;
}
Java solution without the loop. Faster response.
int numberToReverse;//your number
StringBuilder sb=new StringBuilder();
sb.append(numberToReverse);
sb=sb.reverse();
String intermediateString=sb.toString();
int reversedNumber=Integer.parseInt(intermediateString);
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class intreverse
{
public static void main(String...a)throws Exception
{
int no;
int rev = 0;
System.out.println("Enter The no to be reversed");
InputStreamReader str=new InputStreamReader(System.in);
BufferedReader br =new BufferedReader(str);
no=Integer.parseInt(br.readLine().toString());
while(no!=0)
{
rev=rev*10+no%10;
no=no/10;
}
System.out.println(rev);
}
}
public static int reverse(int x) {
boolean negetive = false;
if (x < 0) {
x = Math.abs(x);
negative = true;
}
int y = 0, i = 0;
while (x > 0) {
if (i > 0) {
y *= 10;
}
y += x % 10;
x = x / 10;
i++;
}
return negative ? -y : y;
}
Here is a complete solution(returns 0 if number is overflown):
public int reverse(int x) {
boolean flag = false;
// Helpful to check if int is within range of "int"
long num = x;
// if the number is negative then turn the flag on.
if(x < 0) {
flag = true;
num = 0 - num;
}
// used for the result.
long result = 0;
// continue dividing till number is greater than 0
while(num > 0) {
result = result*10 + num%10;
num= num/10;
}
if(flag) {
result = 0 - result;
}
if(result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
return 0;
}
return (int) result;
}
Scanner input = new Scanner(System.in);
System.out.print("Enter number :");
int num = input.nextInt();
System.out.print("Reverse number :");
int value;
while( num > 0){
value = num % 10;
num /= 10;
System.out.print(value); //value = Reverse
}
int convert (int n)
{
long val = 0;
if(n==0)
return 0;
for(int i = 1; n > exponent(10, (i-1)); i++)
{
int mod = n%( (exponent(10, i))) ;
int index = mod / (exponent(10, i-1));
val *= 10;
val += index;
}
if (val < Integer.MIN_VALUE || val > Integer.MAX_VALUE)
{
throw new IllegalArgumentException
(val + " cannot be cast to int without changing its value.");
}
return (int) val;
}
static int exponent(int m, int n)
{
if(n < 0)
return 0;
if(0 == n)
return 1;
return (m * exponent(m, n-1));
}
It's good that you wrote out your original code. I have another way to code this concept of reversing an integer. I'm only going to allow up to 10 digits. However, I am going to make the assumption that the user will not enter a zero.
if((inputNum <= 999999999)&&(inputNum > 0 ))
{
System.out.print("Your number reversed is: ");
do
{
endInt = inputNum % 10; //to get the last digit of the number
inputNum /= 10;
system.out.print(endInt);
}
While(inputNum != 0);
System.out.println("");
}
else
System.out.println("You used an incorrect number of integers.\n");
System.out.println("Program end");
Even if negative integer is passed then it will give the negative integer
Try This...
public int reverse(int result) {
long newNum=0,old=result;
result=(result>0) ? result:(0-result);
while(result!=0){
newNum*=10;
newNum+=result%10;
result/=10;
if(newNum>Integer.MAX_VALUE||newNum<Integer.MIN_VALUE)
return 0;
}
if(old > 0)
return (int)newNum;
else if(old < 0)
return (int)(newNum*-1);
else
return 0;
}
This is the shortest code to reverse an integer
int i=5263;
System.out.println(Integer.parseInt(new StringBuffer(String.valueOf(i) ).reverse().toString()));
123 maps to 321, which can be calculated as 3*(10^2)+2*(10^1)+1
Two functions are used to calculate (10^N). The first function calculates the value of N. The second function calculates the value for ten to power N.
Function<Integer, Integer> powerN = x -> Double.valueOf(Math.log10(x)).intValue();
Function<Integer, Integer> ten2powerN = y -> Double.valueOf(Math.pow(10, y)).intValue();
// 123 => 321= 3*10^2 + 2*10 + 1
public int reverse(int number) {
if (number < 10) {
return number;
} else {
return (number % 10) * powerN.andThen(ten2powerN).apply(number) + reverse(number / 10);
}
}
If the idea is not to use arrays or string, reversing an integer has to be done by reading the digits of a number from the end one at a time. Below explanation is provided in detail to help the novice.
pseudocode :
lets start with reversed_number = 0 and some value for original_number which needs to be reversed.
the_last_digit = original_number % 10 (i.e, the reminder after dividing by 10)
original_number = original_number/10 (since we already have the last digit, remove the last digit from the original_number)
reversed_number = reversed_number * 10 + last_digit (multiply the reversed_number with 10, so as to add the last_digit to it)
repeat steps 2 to 4, till the original_number becomes 0. When original_number = 0, reversed_number would have the reverse of the original_number.
More info on step 4: If you are provided with a digit at a time, and asked to append it at the end of a number, how would you do it - by moving the original number one place to the left so as to accommodate the new digit. If number 23 has to become 234, you multiply 23 with 10 and then add 4.
234 = 23x10 + 4;
Code:
public static int reverseInt(int original_number) {
int reversed_number = 0;
while (original_number > 0) {
int last_digit = original_number % 10;
original_number = original_number / 10;
reversed_number = reversed_number * 10 + last_digit;
}
return reversed_number;
}
It is an outdated question, but as a reference for others
First of all reversedNum must be initialized to 0;
input%10 is used to get the last digit from input
input/10 is used to get rid of the last digit from input, which you have added to the reversedNum
Let's say input was 135
135 % 10 is 5
Since reversed number was initialized to 0
now reversedNum will be 5
Then we get rid of 5 by dividing 135 by 10
Now input will be just 13
Your code loops through these steps until all digits are added to the reversed number or in other words untill input becomes 0.
while (input != 0) {
reversedNum = reversedNum * 10 + input % 10;
input = input / 10;
}
let a number be 168,
+ input % 10 returns last digit as reminder i.e. 8 but next time it should return 6,hence number must be reduced to 16 from 168, as divide 168 by 10 that results to 16 instead of 16.8 as variable input is supposed to be integer type in the above program.
If you wanna reverse any number like 1234 and you want to revers this number to let it looks like 4321. First of all, initialize 3 variables int org ; int reverse = 0; and int reminder ;
then put your logic like
Scanner input = new Scanner (System.in);
System.out.println("Enter number to reverse ");
int org = input.nextInt();
int getReminder;
int r = 0;
int count = 0;
while (org !=0){
getReminder = org%10;
r = 10 * r + getReminder;
org = org/10;
}
System.out.println(r);
}
A method to get the greatest power of ten smaller or equal to an integer: (in recursion)
public static int powerOfTen(int n) {
if ( n < 10)
return 1;
else
return 10 * powerOfTen(n/10);
}
The method to reverse the actual integer:(in recursion)
public static int reverseInteger(int i) {
if (i / 10 < 1)
return i ;
else
return i%10*powerOfTen(i) + reverseInteger(i/10);
}
You can use recursion to solve this.
first get the length of an integer number by using following recursive function.
int Length(int num,int count){
if(num==0){
return count;
}
else{
count++;
return Lenght(num/10,count);
}
}
and then you can simply multiply remainder of a number by 10^(Length of integer - 1).
int ReturnReverse(int num,int Length,int reverse){
if(Length!=0){
reverse = reverse + ((num%10) * (int)(Math.pow(10,Length-1)));
return ReturnReverse(num/10,Length-1,reverse);
}
return reverse;
}
The whole Source Code :
import java.util.Scanner;
public class ReverseNumbers {
int Length(int num, int count) {
if (num == 0) {
return count;
} else {
return Length(num / 10, count + 1);
}
}
int ReturnReverse(int num, int Length, int reverse) {
if (Length != 0) {
reverse = reverse + ((num % 10) * (int) (Math.pow(10, Length - 1)));
return ReturnReverse(num / 10, Length - 1, reverse);
}
return reverse;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
ReverseNumbers reverseNumbers = new ReverseNumbers();
reverseNumbers.ReturnReverse(N, reverseNumbers.Length(N, 0), reverseNumbers.ReturnReverse(N, reverseNumbers.Length(N, 0), 0));
scanner.close();
}
}
public int getReverseNumber(int number)
{
int reminder = 0, result = 0;
while (number !=0)
{
if (number >= 10 || number <= -10)
{
reminder = number % 10;
result = result + reminder;
result = result * 10;
number = number / 10;
}
else
{
result = result + number;
number /= 10;
}
}
return result;
}
// The above code will work for negative numbers also
Reversing integer
int n, reverse = 0;
Scanner in = new Scanner(System.in);
n = in.nextInt();
while(n != 0)
{
reverse = reverse * 10;
reverse = reverse + n%10;
n = n/10;
}
System.out.println("Reverse of the number is " + reverse);
public static int reverseInt(int i) {
int reservedInt = 0;
try{
String s = String.valueOf(i);
String reversed = reverseWithStringBuilder(s);
reservedInt = Integer.parseInt(reversed);
}catch (NumberFormatException e){
System.out.println("exception caught was " + e.getMessage());
}
return reservedInt;
}
public static String reverseWithStringBuilder(String str) {
System.out.println(str);
StringBuilder sb = new StringBuilder(str);
StringBuilder reversed = sb.reverse();
return reversed.toString();
}
public static int reverse(int x) {
int tmp = x;
int oct = 0;
int res = 0;
while (true) {
oct = tmp % 10;
tmp = tmp / 10;
res = (res+oct)*10;
if ((tmp/10) == 0) {
res = res+tmp;
return res;
}
}
}
public static double reverse(int num)
{
double num1 = num;
double ret = 0;
double counter = 0;
while (num1 > 1)
{
counter++;
num1 = num1/10;
}
while(counter >= 0)
{
int lastdigit = num%10;
ret += Math.pow(10, counter-1) * lastdigit;
num = num/10;
counter--;
}
return ret;
}
I am trying to create a program to validate 10 to 12 digit long number sequences based on the luhn algorithm, but my program keeps on telling me that every number is invalid even though they're not.
This number should be valid, but my code doesn't think so: 8112189876
This number should not be valid, which my program agrees with, as it thinks every number is invalid: 8112189875
Here is my code:
static void luhn(){
System.out.print("Enter number to validate:\n");
String pnr = input.nextLine();
int length = pnr.length();
int sum = 0;
for (int i = 1, pos = length - 1; i < 10; i++, pos--){
char tmp = pnr.charAt(pos);
int num = tmp - 0
int product;
if (i % 2 != 0){
product = num * 1;
}
else{
product = num * 2;
}
if (product > 9)
product -= 9;
sum+= product;
boolean valid = (sum % 10 == 0);
if (valid){
System.out.print("Valid!\r");
}
else{
System.out.print("Invalid!");
}
}
}
use org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit.LUHN_CHECK_DIGIT.isValid(number)
Maven Dependency:
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.5.1</version>
</dependency>
The first thing I see is that you have:
int num = tmp - 0
You should instead have:
int num = tmp - '0';
Secondly, you should be validating your sum outside of the for loop, because you only care about the sum after processing all the digits.
Thirdly, you are starting from the end of the number, and you are not including the first number of your string. Why not use i for both tasks?
Resulting (working) method:
static void luhn(){
System.out.print("Enter number to validate:\n");
String pnr = input.nextLine();
// this only works if you are certain all input will be at least 10 characters
int extraChars = pnr.length() - 10;
if (extraChars < 0) {
throw new IllegalArgumentException("Number length must be at least 10 characters!");
}
pnr = pnr.substring(extraChars, 10 + extraChars);
int sum = 0;
// #3: removed pos
for (int i = 0; i < pnr.length(); i++){
char tmp = pnr.charAt(i);
// #1: fixed the '0' problem
int num = tmp - '0';
int product;
if (i % 2 != 0){
product = num * 1;
}
else{
product = num * 2;
}
if (product > 9)
product -= 9;
sum+= product;
}
// #2: moved check outside for loop
boolean valid = (sum % 10 == 0);
if (valid){
System.out.print("Valid!\r");
}
else{
System.out.print("Invalid!");
}
}
Stylistically, this method would be more useful if, instead of method signature
static void luhn() {
it instead had method signature
static boolean luhn(String input) {
This easily allows your code to get the String from ANY source (a file, hardcoded, etc.) and do anything with the result (print a message as yours does, or do something else). Obviously you would move the System.out.print, input.nextLine(), and if(valid) bits of code outside of this method.
Full refactored program:
import java.util.Scanner;
public class Luhn {
private static Scanner input;
public static void main(String... args) {
input = new Scanner(System.in);
System.out.print("Enter number to validate:\n");
String pnr = input.nextLine();
boolean result = luhn(pnr);
printMessage(result);
input.close();
}
static boolean luhn(String pnr){
// this only works if you are certain all input will be at least 10 characters
int extraChars = pnr.length() - 10;
if (extraChars < 0) {
throw new IllegalArgumentException("Number length must be at least 10 characters!");
}
pnr = pnr.substring(extraChars, 10 + extraChars);
int sum = 0;
for (int i = 0; i < pnr.length(); i++){
char tmp = pnr.charAt(i);
int num = tmp - '0';
int product;
if (i % 2 != 0){
product = num * 1;
}
else{
product = num * 2;
}
if (product > 9)
product -= 9;
sum+= product;
}
return (sum % 10 == 0);
}
private static void printMessage(boolean valid) {
if (valid){
System.out.print("Valid!\r");
}
else{
System.out.print("Invalid!");
}
}
}
I use this function in an app for checking card number validity :
public static boolean Check(String ccNumber)
{
int sum = 0;
boolean alternate = false;
for (int i = ccNumber.length() - 1; i >= 0; i--)
{
int n = Integer.parseInt(ccNumber.substring(i, i + 1));
if (alternate)
{
n *= 2;
if (n > 9)
{
n = (n % 10) + 1;
}
}
sum += n;
alternate = !alternate;
}
return (sum % 10 == 0);
}
Hope it helps,
If you use Java 10 or higher, you can use the following code:
public static boolean luhn(String s) {
IntUnaryOperator sumDigits = n -> n / 10 + n % 10;
var digits = s.chars()
.map(Character::getNumericValue)
.toArray();
return IntStream.rangeClosed(1, digits.length)
.map(i -> digits.length - i)
.map(i -> i % 2 == 0 ? digits[i] : sumDigits.applyAsInt(digits[i] * 2))
.sum() % 10 == 0;
}
It's the functional approach to this algorithm.
You should be subtracting '0' from tmp, not 0. Subtracting 0 returns the ASCII value, which you don't want.
Here's some functions I wrote to both calculate the check digit for a given number and to verify a given number sequence and extract the number from it.
To calculate the check digit for a given number:
/**
* Generates the check digit for a number using Luhn's algorithm described in detail at the following link:
* https://en.wikipedia.org/wiki/Luhn_algorithm
*
* In short the digit is calculated like so:
* 1. From the rightmost digit moving left, double the value of every second digit. If that value is greater than 9,
* subtract 9 from it.
* 2. Sum all of the digits together
* 3. Multiply the sum by 9 and the check digit will be that value modulo 10.
*
* #param number the number to get the Luhn's check digit for
* #return the check digit for the given number
*/
public static int calculateLuhnsCheckDigit(final long number) {
int sum = 0;
boolean alternate = false;
String digits = Long.toString(number);
for (int i = digits.length() - 1; i >= 0; --i) {
int digit = Character.getNumericValue(digits.charAt(i)); // get the digit at the given index
digit = (alternate = !alternate) ? (digit * 2) : digit; // double every other digit
digit = (digit > 9) ? (digit - 9) : digit; // subtract 9 if the value is greater than 9
sum += digit; // add the digit to the sum
}
return (sum * 9) % 10;
}
To verify a sequence of digits using Luhn's algorithm and extract the number:
/**
* Verifies that a given number string is valid according to Luhn's algorithm, which is described in detail here:
* https://en.wikipedia.org/wiki/Luhn_algorithm
*
* In short, validity of the number is determined like so:
* 1. From the rightmost digit (the check digit) moving left, double the value of every second digit. The check
* digit is not doubled; the first digit doubled is the one immediately to the left of the check digit. If that
* value is greater than 9, subtract 9 from it.
* 2. Sum all of the digits together
* 3. If the sum modulo 10 is equal to 0, then the number is valid according to Luhn's algorithm
*
* #param luhnsNumber the number string to verify and extract the number from
* #return an empty Optional if the given string was not valid according to Luhn's algorithm
* an Optional containing the number verified by Luhn's algorithm if the given string passed the check
*/
public static Optional<Long> extractLuhnsNumber(final String luhnsNumber) {
int sum = 0;
boolean alternate = true;
Long number = Long.parseLong(luhnsNumber.substring(0, luhnsNumber.length() - 1));
for (int i = luhnsNumber.length() - 1; i >= 0; --i) {
int digit = Character.getNumericValue(luhnsNumber.charAt(i)); // get the digit at the given index
digit = (alternate = !alternate) ? (digit * 2) : digit; // double every other digit
digit = (digit > 9) ? (digit - 9) : digit; // subtract 9 if the value is greater than 9
sum += digit; // add the digit to the sum
}
return (sum % 10 == 0) ? Optional.of(number) : Optional.empty();
}
Newcomers to this post/question can check appropriate Wikipedia page for solution. Below is the Java code copy-pasted from there.
public class Luhn
{
public static boolean check(String ccNumber)
{
int sum = 0;
boolean alternate = false;
for (int i = ccNumber.length() - 1; i >= 0; i--)
{
int n = Integer.parseInt(ccNumber.substring(i, i + 1));
if (alternate)
{
n *= 2;
if (n > 9)
{
n = (n % 10) + 1;
}
}
sum += n;
alternate = !alternate;
}
return (sum % 10 == 0);
}
}
package randomNumGen;
public class JavaLuhnAlgorithm {
public static void main(String[] args) {
// TODO Auto-generated method stub
validateCreditCardNumber("8112189876");
String imei = "012850003580200";
validateCreditCardNumber(imei);
}
private static void validateCreditCardNumber(String str) {
int[] ints = new int[str.length()];
for (int i = 0; i < str.length(); i++) {
ints[i] = Integer.parseInt(str.substring(i, i + 1));
}
for (int i = ints.length - 2; i >= 0; i = i - 2) {
int j = ints[i];
j = j * 2;
if (j > 9) {
j = j % 10 + 1;
}
ints[i] = j;
}
int sum = 0;
for (int i = 0; i < ints.length; i++) {
sum += ints[i];
}
if (sum % 10 == 0) {
System.out.println(str + " is a valid credit card number");
} else {
System.out.println(str + " is an invalid credit card number");
}
}
}
Can anyone explain to me how to reverse an integer without using array or String. I got this code from online, but not really understand why + input % 10 and divide again.
while (input != 0) {
reversedNum = reversedNum * 10 + input % 10;
input = input / 10;
}
And how to do use this sample code to reverse only odd number. Example I got this input 12345, then it will reverse the odd number to output 531.
Java reverse an int value - Principles
Modding (%) the input int by 10 will extract off the rightmost digit. example: (1234 % 10) = 4
Multiplying an integer by 10 will "push it left" exposing a zero to the right of that number, example: (5 * 10) = 50
Dividing an integer by 10 will remove the rightmost digit. (75 / 10) = 7
Java reverse an int value - Pseudocode:
a. Extract off the rightmost digit of your input number. (1234 % 10) = 4
b. Take that digit (4) and add it into a new reversedNum.
c. Multiply reversedNum by 10 (4 * 10) = 40, this exposes a zero to the right of your (4).
d. Divide the input by 10, (removing the rightmost digit). (1234 / 10) = 123
e. Repeat at step a with 123
Java reverse an int value - Working code
public int reverseInt(int input) {
long reversedNum = 0;
long input_long = input;
while (input_long != 0) {
reversedNum = reversedNum * 10 + input_long % 10;
input_long = input_long / 10;
}
if (reversedNum > Integer.MAX_VALUE || reversedNum < Integer.MIN_VALUE) {
throw new IllegalArgumentException();
}
return (int) reversedNum;
}
You will never do anything like this in the real work-world. However, the process by which you use to solve it without help is what separates people who can solve problems from the ones who want to, but can't unless they are spoon fed by nice people on the blogoblags.
I am not clear about your Odd number.
The way this code works is (it is not a Java specific algorithm)
Eg.
input =2345
first time in the while loop
rev=5 input=234
second time
rev=5*10+4=54 input=23
third time
rev=54*10+3 input=2
fourth time
rev=543*10+2 input=0
So the reversed number is 5432.
If you just want only the odd numbers in the reversed number then.
The code is:
while (input != 0) {
last_digit = input % 10;
if (last_digit % 2 != 0) {
reversedNum = reversedNum * 10 + last_digit;
}
input = input / 10;
}
Simply you can use this
public int getReverseInt(int value) {
int resultNumber = 0;
for (int i = value; i !=0; i /= 10) {
resultNumber = resultNumber * 10 + i % 10;
}
return resultNumber;
}
You can use this method with the given value which you want revers.
while (num != 0) {
rev = rev * 10 + num % 10;
num /= 10;
}
That is the solution I used for this problem, and it works fine.
More details:
num % 10
This statement will get you the last digit from the original number.
num /= 10
This statement will eliminate the last digit from the original number, and hence we are sure that while loop will terminate.
rev = rev * 10 + num % 10
Here rev*10 will shift the value by left and then add the last digit from the original.
If the original number was 1258, and in the middle of the run time we have rev = 85, num = 12 so:
num%10 = 2
rev*10 = 850
rev*10 + num%10 = 852
int aa=456;
int rev=Integer.parseInt(new StringBuilder(aa+"").reverse());
import java.util.Scanner;
public class Reverse_order_integer {
private static Scanner scan;
public static void main(String[] args) {
System.out.println("\t\t\tEnter Number which you want to reverse.\n");
scan = new Scanner(System.in);
int number = scan.nextInt();
int rev_number = reverse(number);
System.out.println("\t\t\tYour reverse Number is = \"" + rev_number
+ "\".\n");
}
private static int reverse(int number) {
int backup = number;
int count = 0;
while (number != 0) {
number = number / 10;
count++;
}
number = backup;
int sum = 0;
for (int i = count; i > 0; i--) {
int sum10 = 1;
int last = number % 10;
for (int j = 1; j < i; j++) {
sum10 = sum10 * 10;
}
sum = sum + (last * sum10);
number = number / 10;
}
return sum;
}
}
See to get the last digit of any number we divide it by 10 so we either achieve zero or a digit which is placed on last and when we do this continuously we get the whole number as an integer reversed.
int number=8989,last_num,sum=0;
while(number>0){
last_num=number%10; // this will give 8989%10=9
number/=10; // now we have 9 in last and now num/ by 10= 898
sum=sum*10+last_number; // sum=0*10+9=9;
}
// last_num=9. number= 898. sum=9
// last_num=8. number =89. sum=9*10+8= 98
// last_num=9. number=8. sum=98*10+9=989
// last_num=8. number=0. sum=989*10+8=9898
// hence completed
System.out.println("Reverse is"+sum);
public static void main(String args[]) {
int n = 0, res = 0, n1 = 0, rev = 0;
int sum = 0;
Scanner scan = new Scanner(System.in);
System.out.println("Please Enter No.: ");
n1 = scan.nextInt(); // String s1=String.valueOf(n1);
int len = (n1 == 0) ? 1 : (int) Math.log10(n1) + 1;
while (n1 > 0) {
rev = res * ((int) Math.pow(10, len));
res = n1 % 10;
n1 = n1 / 10;
// sum+=res; //sum=sum+res;
sum += rev;
len--;
}
// System.out.println("sum No: " + sum);
System.out.println("sum No: " + (sum + res));
}
This will return reverse of integer
Just to add on, in the hope to make the solution more complete.
The logic by #sheki already gave the correct way of reversing an integer in Java. If you assume the input you use and the result you get always fall within the range [-2147483648, 2147483647], you should be safe to use the codes by #sheki. Otherwise, it'll be a good practice to catch the exception.
Java 8 introduced the methods addExact, subtractExact, multiplyExact and toIntExact. These methods will throw ArithmeticException upon overflow. Therefore, you can use the below implementation to implement a clean and a bit safer method to reverse an integer. Generally we can use the mentioned methods to do mathematical calculation and explicitly handle overflow issue, which is always recommended if there's a possibility of overflow in the actual usage.
public int reverse(int x) {
int result = 0;
while (x != 0){
try {
result = Math.multiplyExact(result, 10);
result = Math.addExact(result, x % 10);
x /= 10;
} catch (ArithmeticException e) {
result = 0; // Exception handling
break;
}
}
return result;
}
Java solution without the loop. Faster response.
int numberToReverse;//your number
StringBuilder sb=new StringBuilder();
sb.append(numberToReverse);
sb=sb.reverse();
String intermediateString=sb.toString();
int reversedNumber=Integer.parseInt(intermediateString);
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class intreverse
{
public static void main(String...a)throws Exception
{
int no;
int rev = 0;
System.out.println("Enter The no to be reversed");
InputStreamReader str=new InputStreamReader(System.in);
BufferedReader br =new BufferedReader(str);
no=Integer.parseInt(br.readLine().toString());
while(no!=0)
{
rev=rev*10+no%10;
no=no/10;
}
System.out.println(rev);
}
}
public static int reverse(int x) {
boolean negetive = false;
if (x < 0) {
x = Math.abs(x);
negative = true;
}
int y = 0, i = 0;
while (x > 0) {
if (i > 0) {
y *= 10;
}
y += x % 10;
x = x / 10;
i++;
}
return negative ? -y : y;
}
Here is a complete solution(returns 0 if number is overflown):
public int reverse(int x) {
boolean flag = false;
// Helpful to check if int is within range of "int"
long num = x;
// if the number is negative then turn the flag on.
if(x < 0) {
flag = true;
num = 0 - num;
}
// used for the result.
long result = 0;
// continue dividing till number is greater than 0
while(num > 0) {
result = result*10 + num%10;
num= num/10;
}
if(flag) {
result = 0 - result;
}
if(result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
return 0;
}
return (int) result;
}
Scanner input = new Scanner(System.in);
System.out.print("Enter number :");
int num = input.nextInt();
System.out.print("Reverse number :");
int value;
while( num > 0){
value = num % 10;
num /= 10;
System.out.print(value); //value = Reverse
}
int convert (int n)
{
long val = 0;
if(n==0)
return 0;
for(int i = 1; n > exponent(10, (i-1)); i++)
{
int mod = n%( (exponent(10, i))) ;
int index = mod / (exponent(10, i-1));
val *= 10;
val += index;
}
if (val < Integer.MIN_VALUE || val > Integer.MAX_VALUE)
{
throw new IllegalArgumentException
(val + " cannot be cast to int without changing its value.");
}
return (int) val;
}
static int exponent(int m, int n)
{
if(n < 0)
return 0;
if(0 == n)
return 1;
return (m * exponent(m, n-1));
}
It's good that you wrote out your original code. I have another way to code this concept of reversing an integer. I'm only going to allow up to 10 digits. However, I am going to make the assumption that the user will not enter a zero.
if((inputNum <= 999999999)&&(inputNum > 0 ))
{
System.out.print("Your number reversed is: ");
do
{
endInt = inputNum % 10; //to get the last digit of the number
inputNum /= 10;
system.out.print(endInt);
}
While(inputNum != 0);
System.out.println("");
}
else
System.out.println("You used an incorrect number of integers.\n");
System.out.println("Program end");
Even if negative integer is passed then it will give the negative integer
Try This...
public int reverse(int result) {
long newNum=0,old=result;
result=(result>0) ? result:(0-result);
while(result!=0){
newNum*=10;
newNum+=result%10;
result/=10;
if(newNum>Integer.MAX_VALUE||newNum<Integer.MIN_VALUE)
return 0;
}
if(old > 0)
return (int)newNum;
else if(old < 0)
return (int)(newNum*-1);
else
return 0;
}
This is the shortest code to reverse an integer
int i=5263;
System.out.println(Integer.parseInt(new StringBuffer(String.valueOf(i) ).reverse().toString()));
123 maps to 321, which can be calculated as 3*(10^2)+2*(10^1)+1
Two functions are used to calculate (10^N). The first function calculates the value of N. The second function calculates the value for ten to power N.
Function<Integer, Integer> powerN = x -> Double.valueOf(Math.log10(x)).intValue();
Function<Integer, Integer> ten2powerN = y -> Double.valueOf(Math.pow(10, y)).intValue();
// 123 => 321= 3*10^2 + 2*10 + 1
public int reverse(int number) {
if (number < 10) {
return number;
} else {
return (number % 10) * powerN.andThen(ten2powerN).apply(number) + reverse(number / 10);
}
}
If the idea is not to use arrays or string, reversing an integer has to be done by reading the digits of a number from the end one at a time. Below explanation is provided in detail to help the novice.
pseudocode :
lets start with reversed_number = 0 and some value for original_number which needs to be reversed.
the_last_digit = original_number % 10 (i.e, the reminder after dividing by 10)
original_number = original_number/10 (since we already have the last digit, remove the last digit from the original_number)
reversed_number = reversed_number * 10 + last_digit (multiply the reversed_number with 10, so as to add the last_digit to it)
repeat steps 2 to 4, till the original_number becomes 0. When original_number = 0, reversed_number would have the reverse of the original_number.
More info on step 4: If you are provided with a digit at a time, and asked to append it at the end of a number, how would you do it - by moving the original number one place to the left so as to accommodate the new digit. If number 23 has to become 234, you multiply 23 with 10 and then add 4.
234 = 23x10 + 4;
Code:
public static int reverseInt(int original_number) {
int reversed_number = 0;
while (original_number > 0) {
int last_digit = original_number % 10;
original_number = original_number / 10;
reversed_number = reversed_number * 10 + last_digit;
}
return reversed_number;
}
It is an outdated question, but as a reference for others
First of all reversedNum must be initialized to 0;
input%10 is used to get the last digit from input
input/10 is used to get rid of the last digit from input, which you have added to the reversedNum
Let's say input was 135
135 % 10 is 5
Since reversed number was initialized to 0
now reversedNum will be 5
Then we get rid of 5 by dividing 135 by 10
Now input will be just 13
Your code loops through these steps until all digits are added to the reversed number or in other words untill input becomes 0.
while (input != 0) {
reversedNum = reversedNum * 10 + input % 10;
input = input / 10;
}
let a number be 168,
+ input % 10 returns last digit as reminder i.e. 8 but next time it should return 6,hence number must be reduced to 16 from 168, as divide 168 by 10 that results to 16 instead of 16.8 as variable input is supposed to be integer type in the above program.
If you wanna reverse any number like 1234 and you want to revers this number to let it looks like 4321. First of all, initialize 3 variables int org ; int reverse = 0; and int reminder ;
then put your logic like
Scanner input = new Scanner (System.in);
System.out.println("Enter number to reverse ");
int org = input.nextInt();
int getReminder;
int r = 0;
int count = 0;
while (org !=0){
getReminder = org%10;
r = 10 * r + getReminder;
org = org/10;
}
System.out.println(r);
}
A method to get the greatest power of ten smaller or equal to an integer: (in recursion)
public static int powerOfTen(int n) {
if ( n < 10)
return 1;
else
return 10 * powerOfTen(n/10);
}
The method to reverse the actual integer:(in recursion)
public static int reverseInteger(int i) {
if (i / 10 < 1)
return i ;
else
return i%10*powerOfTen(i) + reverseInteger(i/10);
}
You can use recursion to solve this.
first get the length of an integer number by using following recursive function.
int Length(int num,int count){
if(num==0){
return count;
}
else{
count++;
return Lenght(num/10,count);
}
}
and then you can simply multiply remainder of a number by 10^(Length of integer - 1).
int ReturnReverse(int num,int Length,int reverse){
if(Length!=0){
reverse = reverse + ((num%10) * (int)(Math.pow(10,Length-1)));
return ReturnReverse(num/10,Length-1,reverse);
}
return reverse;
}
The whole Source Code :
import java.util.Scanner;
public class ReverseNumbers {
int Length(int num, int count) {
if (num == 0) {
return count;
} else {
return Length(num / 10, count + 1);
}
}
int ReturnReverse(int num, int Length, int reverse) {
if (Length != 0) {
reverse = reverse + ((num % 10) * (int) (Math.pow(10, Length - 1)));
return ReturnReverse(num / 10, Length - 1, reverse);
}
return reverse;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
ReverseNumbers reverseNumbers = new ReverseNumbers();
reverseNumbers.ReturnReverse(N, reverseNumbers.Length(N, 0), reverseNumbers.ReturnReverse(N, reverseNumbers.Length(N, 0), 0));
scanner.close();
}
}
public int getReverseNumber(int number)
{
int reminder = 0, result = 0;
while (number !=0)
{
if (number >= 10 || number <= -10)
{
reminder = number % 10;
result = result + reminder;
result = result * 10;
number = number / 10;
}
else
{
result = result + number;
number /= 10;
}
}
return result;
}
// The above code will work for negative numbers also
Reversing integer
int n, reverse = 0;
Scanner in = new Scanner(System.in);
n = in.nextInt();
while(n != 0)
{
reverse = reverse * 10;
reverse = reverse + n%10;
n = n/10;
}
System.out.println("Reverse of the number is " + reverse);
public static int reverseInt(int i) {
int reservedInt = 0;
try{
String s = String.valueOf(i);
String reversed = reverseWithStringBuilder(s);
reservedInt = Integer.parseInt(reversed);
}catch (NumberFormatException e){
System.out.println("exception caught was " + e.getMessage());
}
return reservedInt;
}
public static String reverseWithStringBuilder(String str) {
System.out.println(str);
StringBuilder sb = new StringBuilder(str);
StringBuilder reversed = sb.reverse();
return reversed.toString();
}
public static int reverse(int x) {
int tmp = x;
int oct = 0;
int res = 0;
while (true) {
oct = tmp % 10;
tmp = tmp / 10;
res = (res+oct)*10;
if ((tmp/10) == 0) {
res = res+tmp;
return res;
}
}
}
public static double reverse(int num)
{
double num1 = num;
double ret = 0;
double counter = 0;
while (num1 > 1)
{
counter++;
num1 = num1/10;
}
while(counter >= 0)
{
int lastdigit = num%10;
ret += Math.pow(10, counter-1) * lastdigit;
num = num/10;
counter--;
}
return ret;
}
Is there a neater way for getting the number of digits in an int than this method?
int numDigits = String.valueOf(1000).length();
Your String-based solution is perfectly OK, there is nothing "un-neat" about it. You have to realize that mathematically, numbers don't have a length, nor do they have digits. Length and digits are both properties of a physical representation of a number in a specific base, i.e. a String.
A logarithm-based solution does (some of) the same things the String-based one does internally, and probably does so (insignificantly) faster because it only produces the length and ignores the digits. But I wouldn't actually consider it clearer in intent - and that's the most important factor.
The logarithm is your friend:
int n = 1000;
int length = (int)(Math.log10(n)+1);
NB: only valid for n > 0.
The fastest approach: divide and conquer.
Assuming your range is 0 to MAX_INT, then you have 1 to 10 digits. You can approach this interval using divide and conquer, with up to 4 comparisons per each input. First, you divide [1..10] into [1..5] and [6..10] with one comparison, and then each length 5 interval you divide using one comparison into one length 3 and one length 2 interval. The length 2 interval requires one more comparison (total 3 comparisons), the length 3 interval can be divided into length 1 interval (solution) and a length 2 interval. So, you need 3 or 4 comparisons.
No divisions, no floating point operations, no expensive logarithms, only integer comparisons.
Code (long but fast):
if (n < 100000) {
// 5 or less
if (n < 100){
// 1 or 2
if (n < 10)
return 1;
else
return 2;
} else {
// 3 or 4 or 5
if (n < 1000)
return 3;
else {
// 4 or 5
if (n < 10000)
return 4;
else
return 5;
}
}
} else {
// 6 or more
if (n < 10000000) {
// 6 or 7
if (n < 1000000)
return 6;
else
return 7;
} else {
// 8 to 10
if (n < 100000000)
return 8;
else {
// 9 or 10
if (n < 1000000000)
return 9;
else
return 10;
}
}
}
Benchmark (after JVM warm-up) - see code below to see how the benchmark was run:
baseline method (with String.length):
2145ms
log10 method: 711ms = 3.02 times
as fast as baseline
repeated divide: 2797ms = 0.77 times
as fast as baseline
divide-and-conquer: 74ms = 28.99
times as fast as baseline
Full code:
public static void main(String[] args) throws Exception {
// validate methods:
for (int i = 0; i < 1000; i++)
if (method1(i) != method2(i))
System.out.println(i);
for (int i = 0; i < 1000; i++)
if (method1(i) != method3(i))
System.out.println(i + " " + method1(i) + " " + method3(i));
for (int i = 333; i < 2000000000; i += 1000)
if (method1(i) != method3(i))
System.out.println(i + " " + method1(i) + " " + method3(i));
for (int i = 0; i < 1000; i++)
if (method1(i) != method4(i))
System.out.println(i + " " + method1(i) + " " + method4(i));
for (int i = 333; i < 2000000000; i += 1000)
if (method1(i) != method4(i))
System.out.println(i + " " + method1(i) + " " + method4(i));
// work-up the JVM - make sure everything will be run in hot-spot mode
allMethod1();
allMethod2();
allMethod3();
allMethod4();
// run benchmark
Chronometer c;
c = new Chronometer(true);
allMethod1();
c.stop();
long baseline = c.getValue();
System.out.println(c);
c = new Chronometer(true);
allMethod2();
c.stop();
System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
c = new Chronometer(true);
allMethod3();
c.stop();
System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
c = new Chronometer(true);
allMethod4();
c.stop();
System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
}
private static int method1(int n) {
return Integer.toString(n).length();
}
private static int method2(int n) {
if (n == 0)
return 1;
return (int)(Math.log10(n) + 1);
}
private static int method3(int n) {
if (n == 0)
return 1;
int l;
for (l = 0 ; n > 0 ;++l)
n /= 10;
return l;
}
private static int method4(int n) {
if (n < 100000) {
// 5 or less
if (n < 100) {
// 1 or 2
if (n < 10)
return 1;
else
return 2;
} else {
// 3 or 4 or 5
if (n < 1000)
return 3;
else {
// 4 or 5
if (n < 10000)
return 4;
else
return 5;
}
}
} else {
// 6 or more
if (n < 10000000) {
// 6 or 7
if (n < 1000000)
return 6;
else
return 7;
} else {
// 8 to 10
if (n < 100000000)
return 8;
else {
// 9 or 10
if (n < 1000000000)
return 9;
else
return 10;
}
}
}
}
private static int allMethod1() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method1(i);
for (int i = 1000; i < 100000; i += 10)
x = method1(i);
for (int i = 100000; i < 1000000; i += 100)
x = method1(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method1(i);
return x;
}
private static int allMethod2() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method2(i);
for (int i = 1000; i < 100000; i += 10)
x = method2(i);
for (int i = 100000; i < 1000000; i += 100)
x = method2(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method2(i);
return x;
}
private static int allMethod3() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method3(i);
for (int i = 1000; i < 100000; i += 10)
x = method3(i);
for (int i = 100000; i < 1000000; i += 100)
x = method3(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method3(i);
return x;
}
private static int allMethod4() {
int x = 0;
for (int i = 0; i < 1000; i++)
x = method4(i);
for (int i = 1000; i < 100000; i += 10)
x = method4(i);
for (int i = 100000; i < 1000000; i += 100)
x = method4(i);
for (int i = 1000000; i < 2000000000; i += 200)
x = method4(i);
return x;
}
Again, benchmark:
baseline method (with String.length): 2145ms
log10 method: 711ms = 3.02 times as fast as baseline
repeated divide: 2797ms = 0.77 times as fast as baseline
divide-and-conquer: 74ms = 28.99 times as fast as baseline
Edit
After I wrote the benchmark, I took a sneak peak into Integer.toString from Java 6, and I found that it uses:
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
// Requires positive x
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
I benchmarked it against my divide-and-conquer solution:
divide-and-conquer: 104ms
Java 6 solution - iterate and compare: 406ms
Mine is about 4x as fast as the Java 6 solution.
Two comments on your benchmark: Java is a complex environment, what with just-in-time compiling and garbage collection and so forth, so to get a fair comparison, whenever I run a benchmark, I always: (a) enclose the two tests in a loop that runs them in sequence 5 or 10 times. Quite often the runtime on the second pass through the loop is quite different from the first. And (b) After each "approach", I do a System.gc() to try to trigger a garbage collection. Otherwise, the first approach might generate a bunch of objects, but not quite enough to force a garbage collection, then the second approach creates a few objects, the heap is exhausted, and garbage collection runs. Then the second approach is "charged" for picking up the garbage left by the first approach. Very unfair!
That said, neither of the above made a significant difference in this example.
With or without those modifications, I got very different results than you did. When I ran this, yes, the toString approach gave run times of 6400 to 6600 millis, while the log approach topok 20,000 to 20,400 millis. Instead of being slightly faster, the log approach was 3 times slower for me.
Note that the two approaches involve very different costs, so this isn't totally shocking: The toString approach will create a lot of temporary objects that have to be cleaned up, while the log approach takes more intense computation. So maybe the difference is that on a machine with less memory, toString requires more garbage collection rounds, while on a machine with a slower processor, the extra computation of log would be more painful.
I also tried a third approach. I wrote this little function:
static int numlength(int n)
{
if (n == 0) return 1;
int l;
n=Math.abs(n);
for (l=0;n>0;++l)
n/=10;
return l;
}
That ran in 1600 to 1900 millis -- less than 1/3 of the toString approach, and 1/10 the log approach on my machine.
If you had a broad range of numbers, you could speed it up further by starting out dividing by 1,000 or 1,000,000 to reduce the number of times through the loop. I haven't played with that.
Can't leave a comment yet, so I'll post as a separate answer.
The logarithm-based solution doesn't calculate the correct number of digits for very big long integers, for example:
long n = 99999999999999999L;
// correct answer: 17
int numberOfDigits = String.valueOf(n).length();
// incorrect answer: 18
int wrongNumberOfDigits = (int) (Math.log10(n) + 1);
Logarithm-based solution calculates incorrect number of digits in large integers
Using Java
int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;
use import java.lang.Math.*; in the beginning
Using C
int nDigits = floor(log10(abs(the_integer))) + 1;
use inclue math.h in the beginning
Since the number of digits in base 10 of an integer is just 1 + truncate(log10(number)), you can do:
public class Test {
public static void main(String[] args) {
final int number = 1234;
final int digits = 1 + (int)Math.floor(Math.log10(number));
System.out.println(digits);
}
}
Edited because my last edit fixed the code example, but not the description.
Another string approach. Short and sweet - for any integer n.
int length = ("" + n).length();
Marian's solution adapted for long type numbers (up to 9,223,372,036,854,775,807), in case someone want's to Copy&Paste it.
In the program I wrote this for numbers up to 10000 were much more probable, so I made a specific branch for them. Anyway it won't make a significative difference.
public static int numberOfDigits (long n) {
// Guessing 4 digit numbers will be more probable.
// They are set in the first branch.
if (n < 10000L) { // from 1 to 4
if (n < 100L) { // 1 or 2
if (n < 10L) {
return 1;
} else {
return 2;
}
} else { // 3 or 4
if (n < 1000L) {
return 3;
} else {
return 4;
}
}
} else { // from 5 a 20 (albeit longs can't have more than 18 or 19)
if (n < 1000000000000L) { // from 5 to 12
if (n < 100000000L) { // from 5 to 8
if (n < 1000000L) { // 5 or 6
if (n < 100000L) {
return 5;
} else {
return 6;
}
} else { // 7 u 8
if (n < 10000000L) {
return 7;
} else {
return 8;
}
}
} else { // from 9 to 12
if (n < 10000000000L) { // 9 or 10
if (n < 1000000000L) {
return 9;
} else {
return 10;
}
} else { // 11 or 12
if (n < 100000000000L) {
return 11;
} else {
return 12;
}
}
}
} else { // from 13 to ... (18 or 20)
if (n < 10000000000000000L) { // from 13 to 16
if (n < 100000000000000L) { // 13 or 14
if (n < 10000000000000L) {
return 13;
} else {
return 14;
}
} else { // 15 or 16
if (n < 1000000000000000L) {
return 15;
} else {
return 16;
}
}
} else { // from 17 to ...¿20?
if (n < 1000000000000000000L) { // 17 or 18
if (n < 100000000000000000L) {
return 17;
} else {
return 18;
}
} else { // 19? Can it be?
// 10000000000000000000L is'nt a valid long.
return 19;
}
}
}
}
}
How about plain old Mathematics? Divide by 10 until you reach 0.
public static int getSize(long number) {
int count = 0;
while (number > 0) {
count += 1;
number = (number / 10);
}
return count;
}
I see people using String libraries or even using the Integer class. Nothing wrong with that but the algorithm for getting the number of digits is not that complicated. I am using a long in this example but it works just as fine with an int.
private static int getLength(long num) {
int count = 1;
while (num >= 10) {
num = num / 10;
count++;
}
return count;
}
Can I try? ;)
based on Dirk's solution
final int digits = number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));
Marian's Solution, now with Ternary:
public int len(int n){
return (n<100000)?((n<100)?((n<10)?1:2):(n<1000)?3:((n<10000)?4:5)):((n<10000000)?((n<1000000)?6:7):((n<100000000)?8:((n<1000000000)?9:10)));
}
Because we can.
no String API, no utils, no type conversion, just pure java iteration ->
public static int getNumberOfDigits(int input) {
int numOfDigits = 1;
int base = 1;
while (input >= base * 10) {
base = base * 10;
numOfDigits++;
}
return numOfDigits;
}
You can go long for bigger values if you please.
Curious, I tried to benchmark it ...
import org.junit.Test;
import static org.junit.Assert.*;
public class TestStack1306727 {
#Test
public void bench(){
int number=1000;
int a= String.valueOf(number).length();
int b= 1 + (int)Math.floor(Math.log10(number));
assertEquals(a,b);
int i=0;
int s=0;
long startTime = System.currentTimeMillis();
for(i=0, s=0; i< 100000000; i++){
a= String.valueOf(number).length();
s+=a;
}
long stopTime = System.currentTimeMillis();
long runTime = stopTime - startTime;
System.out.println("Run time 1: " + runTime);
System.out.println("s: "+s);
startTime = System.currentTimeMillis();
for(i=0,s=0; i< 100000000; i++){
b= number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));
s+=b;
}
stopTime = System.currentTimeMillis();
runTime = stopTime - startTime;
System.out.println("Run time 2: " + runTime);
System.out.println("s: "+s);
assertEquals(a,b);
}
}
the results are :
Run time 1: 6765
s: 400000000
Run time 2: 6000
s: 400000000
Now I am left to wonder if my benchmark actually means something but I do get consistent results (variations within a ms) over multiple runs of the benchmark itself ... :) It looks like it's useless to try and optimize this...
edit: following ptomli's comment, I replaced 'number' by 'i' in the code above and got the following results over 5 runs of the bench :
Run time 1: 11500
s: 788888890
Run time 2: 8547
s: 788888890
Run time 1: 11485
s: 788888890
Run time 2: 8547
s: 788888890
Run time 1: 11469
s: 788888890
Run time 2: 8547
s: 788888890
Run time 1: 11500
s: 788888890
Run time 2: 8547
s: 788888890
Run time 1: 11484
s: 788888890
Run time 2: 8547
s: 788888890
With design (based on problem). This is an alternate of divide-and-conquer. We'll first define an enum (considering it's only for an unsigned int).
public enum IntegerLength {
One((byte)1,10),
Two((byte)2,100),
Three((byte)3,1000),
Four((byte)4,10000),
Five((byte)5,100000),
Six((byte)6,1000000),
Seven((byte)7,10000000),
Eight((byte)8,100000000),
Nine((byte)9,1000000000);
byte length;
int value;
IntegerLength(byte len,int value) {
this.length = len;
this.value = value;
}
public byte getLenght() {
return length;
}
public int getValue() {
return value;
}
}
Now we'll define a class that goes through the values of the enum and compare and return the appropriate length.
public class IntegerLenght {
public static byte calculateIntLenght(int num) {
for(IntegerLength v : IntegerLength.values()) {
if(num < v.getValue()){
return v.getLenght();
}
}
return 0;
}
}
The run time of this solution is the same as the divide-and-conquer approach.
What about this recursive method?
private static int length = 0;
public static int length(int n) {
length++;
if((n / 10) < 10) {
length++;
} else {
length(n / 10);
}
return length;
}
simple solution:
public class long_length {
long x,l=1,n;
for (n=10;n<x;n*=10){
if (x/n!=0){
l++;
}
}
System.out.print(l);
}
A really simple solution:
public int numLength(int n) {
for (int length = 1; n % Math.pow(10, length) != n; length++) {}
return length;
}
Or instead the length you can check if the number is larger or smaller then the desired number.
public void createCard(int cardNumber, int cardStatus, int customerId) throws SQLException {
if(cardDao.checkIfCardExists(cardNumber) == false) {
if(cardDao.createCard(cardNumber, cardStatus, customerId) == true) {
System.out.println("Card created successfully");
} else {
}
} else {
System.out.println("Card already exists, try with another Card Number");
do {
System.out.println("Enter your new Card Number: ");
scan = new Scanner(System.in);
int inputCardNumber = scan.nextInt();
cardNumber = inputCardNumber;
} while(cardNumber < 95000000);
cardDao.createCard(cardNumber, cardStatus, customerId);
}
}
}
I haven't seen a multiplication-based solution yet. Logarithm, divison, and string-based solutions will become rather unwieldy against millions of test cases, so here's one for ints:
/**
* Returns the number of digits needed to represents an {#code int} value in
* the given radix, disregarding any sign.
*/
public static int len(int n, int radix) {
radixCheck(radix);
// if you want to establish some limitation other than radix > 2
n = Math.abs(n);
int len = 1;
long min = radix - 1;
while (n > min) {
n -= min;
min *= radix;
len++;
}
return len;
}
In base 10, this works because n is essentially being compared to 9, 99, 999... as min is 9, 90, 900... and n is being subtracted by 9, 90, 900...
Unfortunately, this is not portable to long just by replacing every instance of int due to overflow. On the other hand, it just so happens it will work for bases 2 and 10 (but badly fails for most of the other bases). You'll need a lookup table for the overflow points (or a division test... ew)
/**
* For radices 2 &le r &le Character.MAX_VALUE (36)
*/
private static long[] overflowpt = {-1, -1, 4611686018427387904L,
8105110306037952534L, 3458764513820540928L, 5960464477539062500L,
3948651115268014080L, 3351275184499704042L, 8070450532247928832L,
1200757082375992968L, 9000000000000000000L, 5054470284992937710L,
2033726847845400576L, 7984999310198158092L, 2022385242251558912L,
6130514465332031250L, 1080863910568919040L, 2694045224950414864L,
6371827248895377408L, 756953702320627062L, 1556480000000000000L,
3089447554782389220L, 5939011215544737792L, 482121737504447062L,
839967991029301248L, 1430511474609375000L, 2385723916542054400L,
3902460517721977146L, 6269893157408735232L, 341614273439763212L,
513726300000000000L, 762254306892144930L, 1116892707587883008L,
1617347408439258144L, 2316231840055068672L, 3282671350683593750L,
4606759634479349760L};
public static int len(long n, int radix) {
radixCheck(radix);
n = abs(n);
int len = 1;
long min = radix - 1;
while (n > min) {
len++;
if (min == overflowpt[radix]) break;
n -= min;
min *= radix;
}
return len;
}
One wants to do this mostly because he/she wants to "present" it, which mostly mean it finally needs to be "toString-ed" (or transformed in another way) explicitly or implicitly anyway; before it can be presented (printed for example). If that is the case then just try to make the necessary "toString" explicit and count the bits.
We can achieve this using a recursive loop
public static int digitCount(int numberInput, int i) {
while (numberInput > 0) {
i++;
numberInput = numberInput / 10;
digitCount(numberInput, i);
}
return i;
}
public static void printString() {
int numberInput = 1234567;
int digitCount = digitCount(numberInput, 0);
System.out.println("Count of digit in ["+numberInput+"] is ["+digitCount+"]");
}
I wrote this function after looking Integer.java source code.
private static int stringSize(int x) {
final int[] sizeTable = {9, 99, 999, 9_999, 99_999, 999_999, 9_999_999,
99_999_999, 999_999_999, Integer.MAX_VALUE};
for (int i = 0; ; ++i) {
if (x <= sizeTable[i]) {
return i + 1;
}
}
}
One of the efficient ways to count the number of digits in an int variable would be to define a method digitsCounter with a required number of conditional statements.
The approach is simple, we will be checking for each range in which a n digit number can lie:
0 : 9 are Single digit numbers
10 : 99 are Double digit numbers
100 : 999 are Triple digit numbers and so on...
static int digitsCounter(int N)
{ // N = Math.abs(N); // if `N` is -ve
if (0 <= N && N <= 9) return 1;
if (10 <= N && N <= 99) return 2;
if (100 <= N && N <= 999) return 3;
if (1000 <= N && N <= 9999) return 4;
if (10000 <= N && N <= 99999) return 5;
if (100000 <= N && N <= 999999) return 6;
if (1000000 <= N && N <= 9999999) return 7;
if (10000000 <= N && N <= 99999999) return 8;
if (100000000 <= N && N <= 999999999) return 9;
return 10;
}
A cleaner way to do this is to remove the check for the lower limits as it won't be required if we proceed in a sequential manner.
static int digitsCounter(int N)
{
N = N < 0 ? -N : N;
if (N <= 9) return 1;
if (N <= 99) return 2;
if (N <= 999) return 3;
if (N <= 9999) return 4;
if (N <= 99999) return 5;
if (N <= 999999) return 6;
if (N <= 9999999) return 7;
if (N <= 99999999) return 8;
if (N <= 999999999) return 9;
return 10; // Max possible digits in an 'int'
}
Ideally, an integer divided by 10 multiple times will return the number of digits as long as the integer is not zero. As such a simple method to do so can be created as below.
public static int getNumberOfDigits(int number) {
int numberOfDigits = 0;
while(number != 0) {
number /= 10;
numberOfDigits++;
}
return numberOfDigits;
}
It depends on what you mean by "neat". I think the following code is fairly neat, and it runs fast.
It is based on Marian's answer, extended to work with all long values and rendered using the ? : operator.
private static long[] DIGITS = { 1l,
10l,
100l,
1000l,
10000l,
100000l,
1000000l,
10000000l,
100000000l,
1000000000l,
10000000000l,
100000000000l,
1000000000000l,
10000000000000l,
100000000000000l,
1000000000000000l,
10000000000000000l,
100000000000000000l,
1000000000000000000l };
public static int numberOfDigits(final long n)
{
return n == Long.MIN_VALUE ? 19 : n < 0l ? numberOfDigits(-n) :
n < DIGITS[8] ? // 1-8
n < DIGITS[4] ? // 1-4
n < DIGITS[2] ? // 1-2
n < DIGITS[1] ? 1 : 2 : // 1-2
n < DIGITS[3] ? 3 : 4 : // 3-4
n < DIGITS[6] ? // 5-8
n < DIGITS[5] ? 5 : 6 : // 5-6
n < DIGITS[7] ? 7 : 8 : // 7-8
n < DIGITS[16] ? // 9-16
n < DIGITS[12] ? // 9-12
n < DIGITS[10] ? // 9-10
n < DIGITS[9] ? 9 : 10 : // 9-10
n < DIGITS[11] ? 11 : 12 : // 11-12
n < DIGITS[14] ? // 13-16
n < DIGITS[13] ? 13 : 14 : // 13-14
n < DIGITS[15] ? 15 : 16 : // 15-16
n < DIGITS[17] ? 17 : // 17-19
n < DIGITS[18] ? 18 :
19;
}
Here is what such solution looks from the JDK developers. This is JDK 17 (class Long):
/**
* Returns the string representation size for a given long value.
*
* #param x long value
* #return string size
*
* #implNote There are other ways to compute this: e.g. binary search,
* but values are biased heavily towards zero, and therefore linear search
* wins. The iteration results are also routinely inlined in the generated
* code after loop unrolling.
*/
static int stringSize(long x) {
int d = 1;
if (x >= 0) {
d = 0;
x = -x;
}
long p = -10;
for (int i = 1; i < 19; i++) {
if (x > p)
return i + d;
p = 10 * p;
}
return 19 + d;
}
Note that the method takes into account a minus sign, if necessary.
Unfortunately the method is not exposed.
In terms of performance you can see from the comments that the JDK developer has at least given this some thought compared to alternatives. I would guess that
a divide-and-conquer method skewed toward lower numbers would perform slightly
better, because the CPU can do integer comparisons a bit faster than integer
multiplications. But the difference may so small that it is not measurable.
In any case, I wish this method had been exposed in the JDK so that people would not start rolling their own method.
Here's a really simple method I made that works for any number:
public static int numberLength(int userNumber) {
int numberCounter = 10;
boolean condition = true;
int digitLength = 1;
while (condition) {
int numberRatio = userNumber / numberCounter;
if (numberRatio < 1) {
condition = false;
} else {
digitLength++;
numberCounter *= 10;
}
}
return digitLength;
}
The way it works is with the number counter variable is that 10 = 1 digit space. For example .1 = 1 tenth => 1 digit space. Therefore if you have int number = 103342; you'll get 6, because that's the equivalent of .000001 spaces back. Also, does anyone have a better variable name for numberCounter? I can't think of anything better.
Edit: Just thought of a better explanation. Essentially what this while loop is doing is making it so you divide your number by 10, until it's less than one. Essentially, when you divide something by 10 you're moving it back one number space, so you simply divide it by 10 until you reach <1 for the amount of digits in your number.
Here's another version that can count the amount of numbers in a decimal:
public static int repeatingLength(double decimalNumber) {
int numberCounter = 1;
boolean condition = true;
int digitLength = 1;
while (condition) {
double numberRatio = decimalNumber * numberCounter;
if ((numberRatio - Math.round(numberRatio)) < 0.0000001) {
condition = false;
} else {
digitLength++;
numberCounter *= 10;
}
}
return digitLength - 1;
}