Home » Математические операции в JavaScript с использованием операторов
Математические операции в JavaScript с использованием операторов

Математические операции в 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 в серверной среде — это не только веб-разработка. С правильным подходом к математическим операциям ты можешь создавать эффективные инструменты для администрирования серверов, мониторинга и автоматизации. Главное — понимать особенности языка и не забывать про обработку ошибок.


В этой статье собрана информация и материалы из различных интернет-источников. Мы признаем и ценим работу всех оригинальных авторов, издателей и веб-сайтов. Несмотря на то, что были приложены все усилия для надлежащего указания исходного материала, любая непреднамеренная оплошность или упущение не являются нарушением авторских прав. Все упомянутые товарные знаки, логотипы и изображения являются собственностью соответствующих владельцев. Если вы считаете, что какой-либо контент, использованный в этой статье, нарушает ваши авторские права, немедленно свяжитесь с нами для рассмотрения и принятия оперативных мер.

Данная статья предназначена исключительно для ознакомительных и образовательных целей и не ущемляет права правообладателей. Если какой-либо материал, защищенный авторским правом, был использован без должного упоминания или с нарушением законов об авторском праве, это непреднамеренно, и мы исправим это незамедлительно после уведомления. Обратите внимание, что переиздание, распространение или воспроизведение части или всего содержимого в любой форме запрещено без письменного разрешения автора и владельца веб-сайта. Для получения разрешений или дополнительных запросов, пожалуйста, свяжитесь с нами.

Leave a reply

Your email address will not be published. Required fields are marked