- Home »

Математические операции в JavaScript с использованием операторов
Когда работаешь с серверной автоматизацией, скриптами мониторинга или пишешь инструменты для DevOps, JavaScript часто становится твоим лучшим другом. Особенно если ты развертываешь Node.js приложения на своём VPS или крутишь микросервисы. Математические операции в JS — это не просто сложение и вычитание из школьной программы. Это основа для вычислений нагрузки сервера, обработки метрик, работы с временными интервалами и многого другого. Сегодня разберём всё от базовых операторов до подводных камней, которые могут сломать твой production.
## Базовые арифметические операторы
JavaScript предоставляет стандартный набор математических операторов, которые работают достаточно предсказуемо:
// Основные операторы
let a = 10;
let b = 3;
console.log(a + b); // 13 - сложение
console.log(a - b); // 7 - вычитание
console.log(a * b); // 30 - умножение
console.log(a / b); // 3.333... - деление
console.log(a % b); // 1 - остаток от деления
console.log(a ** b); // 1000 - возведение в степень
Интересный факт: оператор `**` (возведение в степень) появился только в ES2016. До этого приходилось использовать `Math.pow()`.
## Операторы присваивания с вычислением
Эти операторы экономят время и делают код более читаемым, особенно в циклах обработки данных:
let serverLoad = 50;
let currentRequests = 10;
serverLoad += currentRequests; // serverLoad = serverLoad + currentRequests
serverLoad -= 5; // serverLoad = serverLoad - 5
serverLoad *= 1.2; // serverLoad = serverLoad * 1.2
serverLoad /= 2; // serverLoad = serverLoad / 2
serverLoad %= 100; // serverLoad = serverLoad % 100
serverLoad **= 2; // serverLoad = serverLoad ** 2
## Операторы инкремента и декремента
Классика жанра для счётчиков и итераторов:
let connectionCount = 0;
// Пост-инкремент: сначала возвращает значение, потом увеличивает
console.log(connectionCount++); // 0
console.log(connectionCount); // 1
// Пре-инкремент: сначала увеличивает, потом возвращает значение
console.log(++connectionCount); // 2
console.log(connectionCount); // 2
// То же самое с декрементом
console.log(connectionCount--); // 2
console.log(--connectionCount); // 0
## Практические примеры для серверной автоматизации
### Мониторинг нагрузки сервера
// Скрипт для вычисления среднего времени отклика
function calculateAverageResponseTime(responses) {
let totalTime = 0;
let validResponses = 0;
for (let i = 0; i < responses.length; i++) {
if (responses[i] > 0) {
totalTime += responses[i];
validResponses++;
}
}
return validResponses > 0 ? totalTime / validResponses : 0;
}
// Вычисление процента использования CPU
function calculateCpuUsage(idle, total) {
return ((total - idle) / total) * 100;
}
// Пример использования
let responseTimes = [120, 45, 89, 156, 78];
let avgTime = calculateAverageResponseTime(responseTimes);
console.log(`Среднее время отклика: ${avgTime.toFixed(2)}ms`);
### Ротация логов по размеру
// Функция для вычисления размера файла лога в MB
function calculateLogSize(bytes) {
return bytes / (1024 * 1024);
}
// Определение необходимости ротации
function needsRotation(currentSize, maxSize = 100) {
return calculateLogSize(currentSize) >= maxSize;
}
// Пример
let logSizeBytes = 104857600; // 100MB в байтах
if (needsRotation(logSizeBytes)) {
console.log("Нужна ротация логов");
}
## Подводные камни и особенности
### Проблема с точностью чисел с плавающей точкой
// Классическая проблема JavaScript
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false
// Решение для финансовых вычислений
function preciseAdd(a, b, precision = 10) {
return Math.round((a + b) * Math.pow(10, precision)) / Math.pow(10, precision);
}
console.log(preciseAdd(0.1, 0.2, 1)); // 0.3
### Деление на ноль и NaN
console.log(5 / 0); // Infinity
console.log(-5 / 0); // -Infinity
console.log(0 / 0); // NaN
console.log(5 % 0); // NaN
// Проверка на корректность результата
function safeDivision(a, b) {
if (b === 0) {
throw new Error("Деление на ноль!");
}
return a / b;
}
## Сравнение с другими языками
| Операция | JavaScript | Python | Java | Особенности JS |
|———-|————|——–|——|—————-|
| Целочисленное деление | `Math.floor(a/b)` | `a // b` | `a / b` | Нет встроенного оператора |
| Остаток от деления | `a % b` | `a % b` | `a % b` | Знак результата как у делимого |
| Возведение в степень | `a ** b` | `a ** b` | `Math.pow(a,b)` | Оператор добавлен в ES2016 |
## Битовые операторы для системных задач
Хотя редко используются в обычной разработке, битовые операторы незаменимы для системного программирования:
// Проверка чётности/нечётности (быстрее чем % 2)
function isEven(num) {
return (num & 1) === 0;
}
// Установка флагов разрешений (как в chmod)
const READ = 4; // 100
const WRITE = 2; // 010
const EXECUTE = 1; // 001
let permissions = READ | WRITE; // 110 (6)
console.log(permissions & READ); // 4 (true)
console.log(permissions & EXECUTE); // 0 (false)
// Быстрое умножение/деление на степени 2
console.log(8 << 1); // 16 (умножение на 2)
console.log(8 >> 1); // 4 (деление на 2)
## Продвинутые техники для автоматизации
### Использование с объектом Math
// Генерация случайных портов для сервисов
function generateRandomPort(min = 3000, max = 9000) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Округление метрик
function formatMetric(value, decimals = 2) {
return Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);
}
// Вычисление времени аптайма
function calculateUptime(startTime) {
const now = Date.now();
const uptimeMs = now - startTime;
const uptimeHours = Math.floor(uptimeMs / (1000 * 60 * 60));
return uptimeHours;
}
### Работа с большими числами
Для работы с большими числами (больше чем `Number.MAX_SAFE_INTEGER`) используй BigInt:
// Обычные числа
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(9007199254740991 + 1); // 9007199254740992
console.log(9007199254740991 + 2); // 9007199254740992 (неточно!)
// BigInt для больших чисел
const bigNum1 = 9007199254740991n;
const bigNum2 = 2n;
console.log(bigNum1 + bigNum2); // 9007199254740993n (точно!)
// Полезно для работы с байтами и размерами файлов
const fileSize = 1024n ** 3n; // 1 GB в байтах
console.log(fileSize); // 1073741824n
## Реальные кейсы использования
### Скрипт мониторинга дискового пространства
#!/usr/bin/env node
const fs = require('fs');
function checkDiskSpace(path = '/') {
const stats = fs.statSync(path);
// Здесь в реальности использовался бы системный вызов
// Это упрощённый пример
const total = 1024 * 1024 * 1024 * 100; // 100GB
const used = 1024 * 1024 * 1024 * 75; // 75GB
const free = total - used;
const usedPercent = (used / total) * 100;
const freePercent = (free / total) * 100;
return {
total: formatBytes(total),
used: formatBytes(used),
free: formatBytes(free),
usedPercent: usedPercent.toFixed(2),
freePercent: freePercent.toFixed(2)
};
}
function formatBytes(bytes) {
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
if (bytes === 0) return '0 B';
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
}
console.log(checkDiskSpace());
### Балансировщик нагрузки на основе весов
class WeightedBalancer {
constructor(servers) {
this.servers = servers;
this.currentWeights = servers.map(s => 0);
}
getNextServer() {
let totalWeight = 0;
let selectedServer = null;
let maxCurrentWeight = -1;
for (let i = 0; i < this.servers.length; i++) {
const server = this.servers[i];
totalWeight += server.weight;
this.currentWeights[i] += server.weight;
if (this.currentWeights[i] > maxCurrentWeight) {
maxCurrentWeight = this.currentWeights[i];
selectedServer = i;
}
}
this.currentWeights[selectedServer] -= totalWeight;
return this.servers[selectedServer];
}
}
// Пример использования
const servers = [
{ name: 'server1', weight: 3 },
{ name: 'server2', weight: 2 },
{ name: 'server3', weight: 1 }
];
const balancer = new WeightedBalancer(servers);
for (let i = 0; i < 12; i++) {
console.log(balancer.getNextServer().name);
}
## Производительность и оптимизация
### Быстрые математические операции
// Быстрая проверка на степень двойки
function isPowerOfTwo(n) {
return n > 0 && (n & (n - 1)) === 0;
}
// Быстрое вычисление следующей степени двойки
function nextPowerOfTwo(n) {
return Math.pow(2, Math.ceil(Math.log(n) / Math.log(2)));
}
// Или через битовые операции (быстрее)
function nextPowerOfTwoBitwise(n) {
n--;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
return n + 1;
}
// Бенчмарк
console.time('Math.pow');
for (let i = 0; i < 1000000; i++) {
nextPowerOfTwo(i % 1000);
}
console.timeEnd('Math.pow');
console.time('Bitwise');
for (let i = 0; i < 1000000; i++) {
nextPowerOfTwoBitwise(i % 1000);
}
console.timeEnd('Bitwise');
## Интеграция с системными инструментами
### Парсинг вывода системных команд
const { execSync } = require('child_process');
function parseCpuInfo() {
const output = execSync('cat /proc/loadavg', { encoding: 'utf8' });
const parts = output.trim().split(' ');
return {
load1min: parseFloat(parts[0]),
load5min: parseFloat(parts[1]),
load15min: parseFloat(parts[2]),
runningProcesses: parseInt(parts[3].split('/')[0]),
totalProcesses: parseInt(parts[3].split('/')[1])
};
}
function getMemoryUsage() {
const output = execSync('free -b', { encoding: 'utf8' });
const lines = output.trim().split('\n');
const memLine = lines[1].split(/\s+/);
const total = parseInt(memLine[1]);
const used = parseInt(memLine[2]);
const free = parseInt(memLine[3]);
return {
total,
used,
free,
usedPercent: (used / total) * 100,
freePercent: (free / total) * 100
};
}
// Использование
console.log('CPU Load:', parseCpuInfo());
console.log('Memory:', getMemoryUsage());
## Полезные библиотеки и инструменты
Для более сложных математических операций рекомендую:
• **Math.js** (https://mathjs.org/) - расширенная математическая библиотека
• **BigNumber.js** - для работы с числами произвольной точности
• **Lodash** - содержит множество утилит для работы с числами
• **D3.js** - отлично подходит для создания графиков метрик
## Автоматизация и DevOps
### Скрипт для автоматического скалирования
class AutoScaler {
constructor(minInstances = 1, maxInstances = 10, targetCpuPercent = 70) {
this.minInstances = minInstances;
this.maxInstances = maxInstances;
this.targetCpuPercent = targetCpuPercent;
this.currentInstances = minInstances;
}
shouldScale(currentCpuPercent) {
const scaleUpThreshold = this.targetCpuPercent * 1.2;
const scaleDownThreshold = this.targetCpuPercent * 0.5;
if (currentCpuPercent > scaleUpThreshold &&
this.currentInstances < this.maxInstances) {
return 'up';
} else if (currentCpuPercent < scaleDownThreshold &&
this.currentInstances > this.minInstances) {
return 'down';
}
return 'none';
}
calculateDesiredInstances(currentCpuPercent) {
const ratio = currentCpuPercent / this.targetCpuPercent;
const desired = Math.ceil(this.currentInstances * ratio);
return Math.max(this.minInstances,
Math.min(this.maxInstances, desired));
}
}
// Пример использования
const scaler = new AutoScaler(2, 20, 70);
console.log(scaler.shouldScale(85)); // 'up'
console.log(scaler.calculateDesiredInstances(85)); // больше текущего
Если планируешь разворачивать серьёзные вычислительные задачи, рассмотри аренду выделенного сервера - там у тебя будет больше контроля над ресурсами.
## Заключение и рекомендации
Математические операторы JavaScript — это мощный инструмент для создания системных скриптов и автоматизации. Основные рекомендации:
• **Всегда проверяй результаты** деления и операций с плавающей точкой
• **Используй BigInt** для работы с большими числами
• **Битовые операции** могут значительно ускорить вычисления
• **Комбинируй с системными командами** для создания полноценных мониторинговых решений
Помни, что JavaScript в серверной среде — это не только веб-разработка. С правильным подходом к математическим операциям ты можешь создавать эффективные инструменты для администрирования серверов, мониторинга и автоматизации. Главное — понимать особенности языка и не забывать про обработку ошибок.
В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.
Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.