diff --git a/src/main/java/com/thealgorithms/maths/HarshadNumber.java b/src/main/java/com/thealgorithms/maths/HarshadNumber.java
index 5792e925a8aa..abe21cb045ae 100644
--- a/src/main/java/com/thealgorithms/maths/HarshadNumber.java
+++ b/src/main/java/com/thealgorithms/maths/HarshadNumber.java
@@ -1,49 +1,78 @@
package com.thealgorithms.maths;
-// Wikipedia for Harshad Number : https://en.wikipedia.org/wiki/Harshad_number
-
+/**
+ * A Harshad number (or Niven number) in a given number base is an integer that
+ * is divisible by the sum of its digits.
+ * For example, 18 is a Harshad number because 18 is divisible by (1 + 8) = 9.
+ * The name "Harshad" comes from the Sanskrit words "harį¹£a" (joy) and "da"
+ * (give), meaning "joy-giver".
+ *
+ * @author Hardvan
+ * @see Harshad Number -
+ * Wikipedia
+ */
public final class HarshadNumber {
private HarshadNumber() {
}
/**
- * A function to check if a number is Harshad number or not
+ * Checks if a number is a Harshad number.
+ * A Harshad number is a positive integer that is divisible by the sum of its
+ * digits.
*
- * @param n The number to be checked
- * @return {@code true} if {@code a} is Harshad number, otherwise
+ * @param n the number to be checked (must be positive)
+ * @return {@code true} if {@code n} is a Harshad number, otherwise
* {@code false}
+ * @throws IllegalArgumentException if {@code n} is less than or equal to 0
*/
public static boolean isHarshad(long n) {
if (n <= 0) {
- return false;
+ throw new IllegalArgumentException("Input must be a positive integer. Received: " + n);
}
- long t = n;
+ long temp = n;
long sumOfDigits = 0;
- while (t > 0) {
- sumOfDigits += t % 10;
- t /= 10;
+ while (temp > 0) {
+ sumOfDigits += temp % 10;
+ temp /= 10;
}
return n % sumOfDigits == 0;
}
/**
- * A function to check if a number is Harshad number or not
+ * Checks if a number represented as a string is a Harshad number.
+ * A Harshad number is a positive integer that is divisible by the sum of its
+ * digits.
*
- * @param s The number in String to be checked
- * @return {@code true} if {@code a} is Harshad number, otherwise
+ * @param s the string representation of the number to be checked
+ * @return {@code true} if the number is a Harshad number, otherwise
* {@code false}
+ * @throws IllegalArgumentException if {@code s} is null, empty, or represents a
+ * non-positive integer
+ * @throws NumberFormatException if {@code s} cannot be parsed as a long
*/
public static boolean isHarshad(String s) {
- final Long n = Long.valueOf(s);
+ if (s == null || s.isEmpty()) {
+ throw new IllegalArgumentException("Input string cannot be null or empty");
+ }
+
+ final long n;
+ try {
+ n = Long.parseLong(s);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Input string must be a valid integer: " + s, e);
+ }
+
if (n <= 0) {
- return false;
+ throw new IllegalArgumentException("Input must be a positive integer. Received: " + n);
}
int sumOfDigits = 0;
for (char ch : s.toCharArray()) {
- sumOfDigits += ch - '0';
+ if (Character.isDigit(ch)) {
+ sumOfDigits += ch - '0';
+ }
}
return n % sumOfDigits == 0;
diff --git a/src/test/java/com/thealgorithms/maths/HarshadNumberTest.java b/src/test/java/com/thealgorithms/maths/HarshadNumberTest.java
index af1c459f3d7f..299e6bd78a99 100644
--- a/src/test/java/com/thealgorithms/maths/HarshadNumberTest.java
+++ b/src/test/java/com/thealgorithms/maths/HarshadNumberTest.java
@@ -1,25 +1,135 @@
package com.thealgorithms.maths;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-public class HarshadNumberTest {
+/**
+ * Test class for {@link HarshadNumber}.
+ * Tests various scenarios including positive cases, edge cases, and exception
+ * handling.
+ */
+class HarshadNumberTest {
+
+ @Test
+ void testValidHarshadNumbers() {
+ // Single digit Harshad numbers (all single digits except 0 are Harshad numbers)
+ Assertions.assertTrue(HarshadNumber.isHarshad(1));
+ Assertions.assertTrue(HarshadNumber.isHarshad(2));
+ Assertions.assertTrue(HarshadNumber.isHarshad(3));
+ Assertions.assertTrue(HarshadNumber.isHarshad(4));
+ Assertions.assertTrue(HarshadNumber.isHarshad(5));
+ Assertions.assertTrue(HarshadNumber.isHarshad(6));
+ Assertions.assertTrue(HarshadNumber.isHarshad(7));
+ Assertions.assertTrue(HarshadNumber.isHarshad(8));
+ Assertions.assertTrue(HarshadNumber.isHarshad(9));
+
+ // Two digit Harshad numbers
+ Assertions.assertTrue(HarshadNumber.isHarshad(10)); // 10 / (1 + 0) = 10
+ Assertions.assertTrue(HarshadNumber.isHarshad(12)); // 12 / (1 + 2) = 4
+ Assertions.assertTrue(HarshadNumber.isHarshad(18)); // 18 / (1 + 8) = 2
+ Assertions.assertTrue(HarshadNumber.isHarshad(20)); // 20 / (2 + 0) = 10
+ Assertions.assertTrue(HarshadNumber.isHarshad(21)); // 21 / (2 + 1) = 7
+
+ // Three digit Harshad numbers
+ Assertions.assertTrue(HarshadNumber.isHarshad(100)); // 100 / (1 + 0 + 0) = 100
+ Assertions.assertTrue(HarshadNumber.isHarshad(102)); // 102 / (1 + 0 + 2) = 34
+ Assertions.assertTrue(HarshadNumber.isHarshad(108)); // 108 / (1 + 0 + 8) = 12
+
+ // Large Harshad numbers
+ Assertions.assertTrue(HarshadNumber.isHarshad(1000)); // 1000 / (1 + 0 + 0 + 0) = 1000
+ Assertions.assertTrue(HarshadNumber.isHarshad(1002)); // 1002 / (1 + 0 + 0 + 2) = 334
+ Assertions.assertTrue(HarshadNumber.isHarshad(999999999)); // 999999999 / (9*9) = 12345679
+ }
@Test
- public void harshadNumber() {
+ void testInvalidHarshadNumbers() {
+ // Numbers that are not Harshad numbers
+ Assertions.assertFalse(HarshadNumber.isHarshad(11)); // 11 / (1 + 1) = 5.5
+ Assertions.assertFalse(HarshadNumber.isHarshad(13)); // 13 / (1 + 3) = 3.25
+ Assertions.assertFalse(HarshadNumber.isHarshad(17)); // 17 / (1 + 7) = 2.125
+ Assertions.assertFalse(HarshadNumber.isHarshad(19)); // 19 / (1 + 9) = 1.9
+ Assertions.assertFalse(HarshadNumber.isHarshad(23)); // 23 / (2 + 3) = 4.6
+ Assertions.assertFalse(HarshadNumber.isHarshad(101)); // 101 / (1 + 0 + 1) = 50.5
+ }
- assertTrue(HarshadNumber.isHarshad(18));
- assertFalse(HarshadNumber.isHarshad(-18));
- assertFalse(HarshadNumber.isHarshad(19));
- assertTrue(HarshadNumber.isHarshad(999999999));
- assertFalse(HarshadNumber.isHarshad(0));
+ @Test
+ void testZeroThrowsException() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad(0));
+ }
- assertTrue(HarshadNumber.isHarshad("18"));
- assertFalse(HarshadNumber.isHarshad("-18"));
- assertFalse(HarshadNumber.isHarshad("19"));
- assertTrue(HarshadNumber.isHarshad("999999999"));
- assertTrue(HarshadNumber.isHarshad("99999999999100"));
+ @Test
+ void testNegativeNumbersThrowException() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad(-1));
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad(-18));
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad(-100));
+ }
+
+ @Test
+ void testValidHarshadNumbersWithString() {
+ // Single digit Harshad numbers
+ Assertions.assertTrue(HarshadNumber.isHarshad("1"));
+ Assertions.assertTrue(HarshadNumber.isHarshad("2"));
+ Assertions.assertTrue(HarshadNumber.isHarshad("9"));
+
+ // Two digit Harshad numbers
+ Assertions.assertTrue(HarshadNumber.isHarshad("10"));
+ Assertions.assertTrue(HarshadNumber.isHarshad("12"));
+ Assertions.assertTrue(HarshadNumber.isHarshad("18"));
+
+ // Large Harshad numbers
+ Assertions.assertTrue(HarshadNumber.isHarshad("1000"));
+ Assertions.assertTrue(HarshadNumber.isHarshad("999999999"));
+ Assertions.assertTrue(HarshadNumber.isHarshad("99999999999100"));
+ }
+
+ @Test
+ void testInvalidHarshadNumbersWithString() {
+ // Numbers that are not Harshad numbers
+ Assertions.assertFalse(HarshadNumber.isHarshad("11"));
+ Assertions.assertFalse(HarshadNumber.isHarshad("13"));
+ Assertions.assertFalse(HarshadNumber.isHarshad("19"));
+ Assertions.assertFalse(HarshadNumber.isHarshad("23"));
+ }
+
+ @Test
+ void testStringWithZeroThrowsException() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad("0"));
+ }
+
+ @Test
+ void testStringWithNegativeNumbersThrowsException() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad("-1"));
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad("-18"));
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad("-100"));
+ }
+
+ @Test
+ void testNullStringThrowsException() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad(null));
+ }
+
+ @Test
+ void testEmptyStringThrowsException() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad(""));
+ }
+
+ @Test
+ void testInvalidStringThrowsException() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad("abc"));
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad("12.5"));
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad("12a"));
+ Assertions.assertThrows(IllegalArgumentException.class, () -> HarshadNumber.isHarshad(" 12 "));
+ }
+
+ @Test
+ void testMaxLongValue() {
+ // Test with a large number close to Long.MAX_VALUE
+ long largeHarshadCandidate = 9223372036854775800L;
+ // This specific number may or may not be Harshad, just testing it doesn't crash
+ try {
+ HarshadNumber.isHarshad(largeHarshadCandidate);
+ } catch (Exception e) {
+ Assertions.fail("Should not throw exception for valid large numbers");
+ }
}
}