Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Знаковые числа (Signed Numbers)
Знаковые числа (Signed Numbers) — это целые числа, которые могут быть как положительными, так и отрицательными. Они используют один бит для обозначения знака числа, а остальные биты — для представления абсолютного значения.
Противоположность: беззнаковые числа
Беззнаковые числа (Unsigned Numbers) — используют все биты для представления только положительных значений.
В Java
Java работает только со знаковыми числами для целочисленных типов.
Целочисленные типы в Java
// Знаковые целые типы
byte value1 = -128; // 8 бит: от -128 до 127
short value2 = -32768; // 16 бит: от -32768 до 32767
int value3 = -2147483648; // 32 бита: от -2147483648 до 2147483647
long value4 = -9223372036854775808L; // 64 бита: от -2^63 до 2^63-1
// Положительные значения
int positive = 100;
int negative = -100;
int zero = 0;
Таблица границ типов
Тип | Размер | Минимум | Максимум
--------|---------|----------------------|----------------------
byte | 8 бит | -128 | 127
short | 16 бит | -32,768 | 32,767
int | 32 бита | -2,147,483,648 | 2,147,483,647
long | 64 бита | -9.22e18 | 9.22e18
Как представляются знаковые числа в памяти
Дополнительный код (Two's Complement) — это метод, используемый в современных компьютерах.
Пример: число 5 в 8 битах
5 = 00000101
Пример: число -5 в 8 битах
Шаг 1: Инвертируем биты числа 5
00000101 → 11111010
Шаг 2: Добавляем 1
11111010 + 1 = 11111011
-5 = 11111011
Проверка:
11111011 + 00000101 = 100000000
(переполнение игнорируется, остаётся 0)
Практические примеры в Java
public class SignedNumbersExample {
public static void main(String[] args) {
// Положительные и отрицательные числа
int positive = 42;
int negative = -42;
System.out.println("Положительное: " + positive); // 42
System.out.println("Отрицательное: " + negative); // -42
// Границы int
int max = Integer.MAX_VALUE; // 2147483647
int min = Integer.MIN_VALUE; // -2147483648
System.out.println("Max int: " + max);
System.out.println("Min int: " + min);
// Переполнение
int overflow = max + 1;
System.out.println("Max + 1: " + overflow); // -2147483648 (обойдёт вокруг)
// Бинарное представление
System.out.println(Integer.toBinaryString(5)); // 101
System.out.println(Integer.toBinaryString(-5)); // 11111111111111111111111111111011
}
}
Проблемы при работе со знаковыми числами
1. Переполнение (Integer Overflow)
int max = Integer.MAX_VALUE; // 2147483647
int overflow = max + 1; // -2147483648 ("обнулился")
// Это может привести к ошибкам
public int multiply(int a, int b) {
return a * b; // Может переполниться!
}
// Решение: использовать long
public long multiply(int a, int b) {
return (long) a * b;
}
2. Неправильное сравнение
int negative = -1;
int positive = 1;
System.out.println(negative < positive); // true (правильно)
System.out.println(negative < 0); // true (правильно)
System.out.println(Integer.compare(negative, positive)); // -1 (правильно)
3. Побитовые операции
int value = -5;
// Побитовое НЕ (NOT)
int notValue = ~value;
System.out.println(~(-5)); // 4
// Сдвиг вправо (арифметический)
int rightShift = value >> 1;
System.out.println((-5) >> 1); // -3 (знак сохраняется)
// Сдвиг вправо (логический)
int logicalShift = value >>> 1;
System.out.println((-5) >>> 1); // 2147483645
Когда нужны беззнаковые числа
Java не имеет встроенных беззнаковых типов, но в Java 8+ добавлены методы для работы с беззнаковыми значениями:
public class UnsignedExample {
public static void main(String[] args) {
// Эмуляция беззнакового int
int unsignedValue = -1; // В памяти: 0xFFFFFFFF
// Преобразуем в строку как беззнаковое
String unsignedString = Integer.toUnsignedString(unsignedValue);
System.out.println(unsignedString); // 4294967295
// Сравнение беззнаковых значений
int a = -1; // 0xFFFFFFFF
int b = 1;
System.out.println(a < b); // true (как знаковые)
System.out.println(Integer.compareUnsigned(a, b)); // 1 (a > b как беззнаковые)
// Деление беззнаковых значений
int dividend = -1; // 0xFFFFFFFF (4294967295 как беззнаковое)
int divisor = 2;
System.out.println(Integer.divideUnsigned(dividend, divisor)); // 2147483647
}
}
Сравнение: знаковые vs беззнаковые
Бинарное представление | Знаковое | Беззнаковое
----------------------|----------|------------
00000101 | 5 | 5
11111011 | -5 | 251
11111111 | -1 | 255
Практическое применение
public class PaymentProcessor {
// Правильно: используем долгие для денег
public long calculateTotal(int price, int quantity) {
return (long) price * quantity; // Избегаем переполнения
}
// Проверка диапазонов
public boolean isValidAge(int age) {
return age >= 0 && age <= 120;
}
// Работа с битами
public boolean isBitSet(byte value, int bitIndex) {
return (value & (1 << bitIndex)) != 0;
}
// Установка бита
public byte setBit(byte value, int bitIndex) {
return (byte) (value | (1 << bitIndex));
}
}
Ключевые моменты
- Java использует знаковые числа для всех целых типов
- Дополнительный код — метод хранения отрицательных чисел
- Переполнение может привести к ошибкам — нужна проверка границ
- Побитовые операции работают иначе с отрицательными числами
- Для больших значений используйте long или BigInteger
- Для беззнаковых операций используйте методы Integer.compareUnsigned и т.д.
Понимание знаковых чисел критично для работы с низкоуровневыми операциями, оптимизацией памяти и предотвращением ошибок переполнения.