diff --git a/README.md b/README.md
index d19c534..447b414 100644
--- a/README.md
+++ b/README.md
@@ -145,6 +145,7 @@ These changes improve throughput and reduce memory pressure when working with la
- [formatList](#formatlist) - Formats an array of strings into a human-readable list with proper commas and "and".
- [formatToOctal](#formattotoctal) - Converts a decimal number to octal, optional "0o" prefix.
- [formatTemperature](#formattemperature) - Converts temperatures between Celsius, Fahrenheit, and Kelvin.
+- [formatToBinary](#formattobinary) - Converts a decimal integer to a binary string with optional bit grouping.
- [formatToHexadecimal](#formattohexadecimal) - Converts temperatures between Celsius, Fahrenheit, and Kelvin.
- [formatToDecimal](#formattodecimal) - Converts base-2/8/16 strings to decimal.
@@ -1532,6 +1533,36 @@ Notes:
- Kelvin values are rendered without the degree symbol (e.g., "298.15K").
- An error is thrown for invalid conversions or non-numeric input values.
+#### `formatToBinary(num, options)`
+
+Converts a decimal integer to its binary (base-2) string representation with optional grouping from the least significant bit for readability. Supports negative numbers.
+
+```javascript
+import { formatToBinary } from 'stringzy';
+
+// Basic conversions
+formatToBinary(5); // "101"
+formatToBinary(10); // "1010"
+formatToBinary(255); // "11111111"
+formatToBinary(0); // "0"
+formatToBinary(-5); // "-101"
+
+// Grouping from right to left (no left-padding)
+formatToBinary(255, { group: 4 }); // "1111 1111"
+formatToBinary(10, { group: 2 }); // "10 10"
+formatToBinary(-255, { group: 4 }); // "-1111 1111"
+
+// Invalid cases
+formatToBinary(3.14); // TypeError (must be an integer)
+formatToBinary('5'); // TypeError (input must be a number)
+formatToBinary(10, { group: 0 }); // TypeError (group must be positive integer)
+```
+
+| Parameter | Type | Default | Description |
+| --------- | ------ | ------- | ------------------------------------------------ |
+| num | number | required| The decimal integer to convert to binary. |
+| options | object | `{}` | Optional configuration. |
+| - group | number | — | Positive integer; bits per group (right-to-left) |
#### formatToHexadecimal(num, options)
Converts a decimal number into its hexadecimal (base-16) string representation.
Supports optional prefix "0x" and lowercase formatting.
diff --git a/src/formatting/binary.ts b/src/formatting/binary.ts
new file mode 100644
index 0000000..64b8f43
--- /dev/null
+++ b/src/formatting/binary.ts
@@ -0,0 +1,57 @@
+/**
+ * Converts a decimal integer to its binary (base-2) string representation.
+ *
+ * - Supports negative numbers (prefixed with '-')
+ * - Optional grouping from the least significant bit for readability
+ *
+ * Examples:
+ * 5 → "101"
+ * 10 → "1010"
+ * 255 → "11111111"
+ * 0 → "0"
+ *
+ * Grouping examples (from right to left):
+ * formatToBinary(255, { group: 4 }) → "1111 1111"
+ * formatToBinary(10, { group: 2 }) → "10 10"
+ *
+ * @param {number} num - The decimal integer to convert.
+ * @param {{ group?: number }} [options] - Optional grouping configuration.
+ * @returns {string} The binary string representation.
+ * @throws {TypeError} If input is not a number, is NaN, or not an integer.
+ */
+export function formatToBinary(num: number, options?: { group?: number }): string {
+ if (typeof num !== 'number' || Number.isNaN(num)) {
+ throw new TypeError('Input must be a number');
+ }
+
+ if (!Number.isInteger(num)) {
+ throw new TypeError('Input must be an integer');
+ }
+
+ const isNegative = num < 0;
+ const absoluteValue = Math.abs(num);
+
+ // Handle zero explicitly to avoid "-0" or empty strings
+ const core = absoluteValue.toString(2);
+
+ const groupSize = options?.group;
+ if (groupSize !== undefined) {
+ if (
+ typeof groupSize !== 'number' ||
+ Number.isNaN(groupSize) ||
+ !Number.isInteger(groupSize) ||
+ groupSize <= 0
+ ) {
+ throw new TypeError('Group size must be a positive integer');
+ }
+ }
+
+ const grouped =
+ groupSize && core.length > groupSize
+ ? core.replace(new RegExp(`\\B(?=(\\d{${groupSize}})+(?!\\d))`, 'g'), ' ')
+ : core;
+
+ return isNegative ? `-${grouped}` : grouped;
+}
+
+
diff --git a/src/formatting/index.ts b/src/formatting/index.ts
index 86be34e..cfc69de 100644
--- a/src/formatting/index.ts
+++ b/src/formatting/index.ts
@@ -10,6 +10,7 @@ export { formatOrdinal } from './ordinal';
export { formatList } from './listToString';
export { formatToOctal } from './octal';
export { formatTemperature } from './temperature';
+export { formatToBinary } from './binary';
export { formatToHexadecimal } from './hexadecimal';
export { formatToDecimal } from './decimal';
@@ -25,6 +26,7 @@ import { formatOrdinal } from './ordinal';
import { formatList } from './listToString';
import { formatToOctal } from './octal';
import { formatTemperature } from './temperature';
+import { formatToBinary } from './binary';
import { formatToHexadecimal } from './hexadecimal';
import { formatToDecimal } from './decimal';
@@ -40,7 +42,8 @@ export const formatting = {
formatOrdinal,
formatList,
formatTemperature,
+ formatToBinary,
formatToHexadecimal,
formatToOctal,
- formatToDecimal,
+ formatToDecimal
};
diff --git a/src/tests/formatting/binary.test.ts b/src/tests/formatting/binary.test.ts
new file mode 100644
index 0000000..d49255a
--- /dev/null
+++ b/src/tests/formatting/binary.test.ts
@@ -0,0 +1,59 @@
+import { describe, it } from 'node:test';
+import assert from 'node:assert';
+import { formatToBinary } from '../../formatting/binary';
+
+describe('formatToBinary', () => {
+ it('converts standard positive integers', () => {
+ assert.strictEqual(formatToBinary(5), '101');
+ assert.strictEqual(formatToBinary(10), '1010');
+ assert.strictEqual(formatToBinary(255), '11111111');
+ assert.strictEqual(formatToBinary(1), '1');
+ assert.strictEqual(formatToBinary(2), '10');
+ });
+
+ it('handles zero', () => {
+ assert.strictEqual(formatToBinary(0), '0');
+ });
+
+ it('prefixes negative numbers with a minus sign', () => {
+ assert.strictEqual(formatToBinary(-5), '-101');
+ assert.strictEqual(formatToBinary(-10), '-1010');
+ });
+
+ it('supports optional grouping from right to left (LSB first)', () => {
+ assert.strictEqual(formatToBinary(255, { group: 4 }), '1111 1111');
+ assert.strictEqual(formatToBinary(10, { group: 2 }), '10 10');
+ assert.strictEqual(formatToBinary(5, { group: 4 }), '101'); // no padding on the left
+ assert.strictEqual(formatToBinary(1023, { group: 4 }), '11 1111 1111');
+ });
+
+ it('applies grouping with negative numbers', () => {
+ assert.strictEqual(formatToBinary(-255, { group: 4 }), '-1111 1111');
+ });
+
+ it('handles large integers (MAX_SAFE_INTEGER)', () => {
+ const expected = Number.MAX_SAFE_INTEGER.toString(2);
+ assert.strictEqual(formatToBinary(Number.MAX_SAFE_INTEGER), expected);
+ });
+
+ it('throws TypeError for invalid inputs (type/NaN)', () => {
+ assert.throws(() => formatToBinary('5' as any), /Input must be a number/);
+ assert.throws(() => formatToBinary(null as any), /Input must be a number/);
+ assert.throws(() => formatToBinary(undefined as any), /Input must be a number/);
+ assert.throws(() => formatToBinary(NaN as any), /Input must be a number/);
+ });
+
+ it('throws TypeError for non-integer numbers', () => {
+ assert.throws(() => formatToBinary(3.14 as any), /Input must be an integer/);
+ assert.throws(() => formatToBinary(-2.5 as any), /Input must be an integer/);
+ });
+
+ it('throws TypeError for invalid group size', () => {
+ assert.throws(() => formatToBinary(10, { group: 0 }), /Group size must be a positive integer/);
+ assert.throws(() => formatToBinary(10, { group: -1 }), /Group size must be a positive integer/);
+ assert.throws(() => formatToBinary(10, { group: 2.5 as any }), /Group size must be a positive integer/);
+ assert.throws(() => formatToBinary(10, { group: '4' as any }), /Group size must be a positive integer/);
+ });
+});
+
+