Tags
code, fun, java, math, mathematics, maths, narcissistic numbers, number, numbers, recreational mathematics
Finally, I pulled my finger out of somewhere and wrote some Java code to calculate all Narcissistic Numbers. I ran it for numbers up to 9 digits and it took about 30 minutes in total. The time taken will increase exponentially, the more digits you run it for.
I’m sure you code/number buffs out there could write a more elegant solution to the problem – please let me know if you do.
Here’s a sample of the output from this code;
DIGITS: 3 153 370 371 407 DIGITS: 4 1634 8208 9474 DIGITS: 5 54748 92727 93084 DIGITS: 6 548834 DIGITS: 7 1741725 4210818 9800817 9926315 DIGITS: 8 24678050 24678051 88593477 DONE.
Or if you decide to run this, let me know how far you got. Here is the breakdown of the code, followed by the full class for you to copy/paste.
Let’s use some math libraries to make the job easier:
import java.math.BigDecimal; // We need this class for the correct level of precision import java.math.MathContext; // This class is used to by BigDecimal methods to determine precision
We define the starting and ending number of digits to process:
public class NarcissismItself { static final int LO_RANGE = 3; // From this number of digits... static final int HI_RANGE = 8; // ...to this number of digits. // Maximum 39. No Narcissistic numbers from 40 digits. Mathematical fact. // After 9, it can take a long time to run. static final int CHAR0 = Integer.valueOf((char)'0'); // Used later to calculate char/int conversion offset
The outer loop iterates through the numbers of digits we wish to process:
public static void main(String[] args) { Integer iDigits = LO_RANGE; do { // Iterate through the required numbers of digits iterateNarcissisticNumbers(iDigits); iDigits++; } while (iDigits <= HI_RANGE); System.out.println("DONE."); }
We work out the start and ending number for the number of digits in the current iteration:
private static void iterateNarcissisticNumbers(Integer iDigits) { System.out.print("DIGITS: "); System.out.print(iDigits); System.out.println(); // Calculate starting number, based on digits e.g. 7 digits = 1000000 BigDecimal bdLo = new BigDecimal(10).pow(iDigits-1, new MathContext(40)); // Calculate ending number, based on digits e.g. 7 digits = 9999999 BigDecimal bdHi = new BigDecimal(10).pow(iDigits, new MathContext(40)).subtract(new BigDecimal(1)); bdLo.setScale(0); // No decimals bdHi.setScale(0); // No decimals // Check all numbers between starting and ending numbers checkNarcissisticNumber(bdLo, bdHi, iDigits); }
We iterate through each number in the range and check whether each is Narcissistic:
private static void checkNarcissisticNumber(BigDecimal bdLo, BigDecimal bdHi, int iDigits) { BigDecimal bdLoop = bdLo.subtract(new BigDecimal(1)); do { // For all candidate numbers, check whether Narcissistic bdLoop = bdLoop.add(new BigDecimal(1)); check1NarcissisticNumber(bdLoop, iDigits); } while ((bdLoop.compareTo(bdHi) == -1)); }
Here’s the code that checks an individual number for Narcissism:
private static void check1NarcissisticNumber(BigDecimal bdNumber, int iDigits) { BigDecimal accumulation = new BigDecimal(0); for (char sX : bdNumber.toPlainString().toCharArray()) { // Iterate through all digits int charVal = Integer.valueOf(sX)-CHAR0; // Convert char to int BigDecimal accum = new BigDecimal(charVal).pow(iDigits,new MathContext(40)); // Raise to power based on digits accumulation = accumulation.add(accum); // Add to accumulated figure } if (bdNumber.compareTo(accumulation) == 0) { // Is the accumulated number the same as the original number? System.out.print(bdNumber.toPlainString()); // Yes? Then it is Narcissistic. System.out.println(); } }
Finally, we close off the class code block:
}
The full class is here in its entirety:
import java.math.BigDecimal; // We need this class for the correct level of precision import java.math.MathContext; // This class is used to by BigDecimal methods to determine precision public class NarcissismItself { static final int LO_RANGE = 3; // From this number of digits... static final int HI_RANGE = 8; // ...to this number of digits. // Maximum 39. No Narcissistic numbers from 40 digits. Mathematical fact. // After 9, it can take a long time to run. static final int CHAR0 = Integer.valueOf((char)'0'); // Used later to calculate char/int conversion offset //-------------------------------------- public static void main(String[] args) { Integer iDigits = LO_RANGE; do { // Iterate through the required numbers of digits iterateNarcissisticNumbers(iDigits); iDigits++; } while (iDigits <= HI_RANGE); System.out.println("DONE."); } //--------------------------------------------------------------- private static void iterateNarcissisticNumbers(Integer iDigits) { System.out.print("DIGITS: "); System.out.print(iDigits); System.out.println(); // Calculate starting number, based on digits e.g. 7 digits = 1000000 BigDecimal bdLo = new BigDecimal(10).pow(iDigits-1, new MathContext(40)); // Calculate ending number, based on digits e.g. 7 digits = 9999999 BigDecimal bdHi = new BigDecimal(10).pow(iDigits, new MathContext(40)).subtract(new BigDecimal(1)); bdLo.setScale(0); // No decimals bdHi.setScale(0); // No decimals // Check all numbers between starting and ending numbers checkNarcissisticNumber(bdLo, bdHi, iDigits); } //------------------------------------------------------------------------------------------ private static void checkNarcissisticNumber(BigDecimal bdLo, BigDecimal bdHi, int iDigits) { BigDecimal bdLoop = bdLo.subtract(new BigDecimal(1)); do { // For all candidate numbers, check whether Narcissistic bdLoop = bdLoop.add(new BigDecimal(1)); check1NarcissisticNumber(bdLoop, iDigits); } while ((bdLoop.compareTo(bdHi) == -1)); } //------------------------------------------------------------------------------ private static void check1NarcissisticNumber(BigDecimal bdNumber, int iDigits) { BigDecimal accumulation = new BigDecimal(0); for (char sX : bdNumber.toPlainString().toCharArray()) { // Iterate through all digits int charVal = Integer.valueOf(sX)-CHAR0; // Convert char to int BigDecimal accum = new BigDecimal(charVal).pow(iDigits,new MathContext(40)); // Raise to power based on digits accumulation = accumulation.add(accum); // Add to accumulated figure } if (bdNumber.compareTo(accumulation) == 0) { // Is the accumulated number the same as the original number? System.out.print(bdNumber.toPlainString()); // Yes? Then it is Narcissistic. System.out.println(); } } }