byte + byte = int ... почему? - PullRequest
346 голосов
/ 02 июня 2009

Глядя на этот код C #:

byte x = 1;
byte y = 2;
byte z = x + y; // ERROR: Cannot implicitly convert type 'int' to 'byte'

Результат любой математики, выполненной для byte (или short) типов, неявно приводится к целому числу. Решением является явное приведение результата обратно к байту:

byte z = (byte)(x + y); // this works

Что мне интересно, почему? Это архитектурно? Философская

Имеем:

  • int + int = int
  • long + long = long
  • float + float = float
  • double + double = double

Так почему бы и нет:

  • byte + byte = byte
  • short + short = short?

Немного предыстории: я выполняю длинный список вычислений для «малых чисел» (т. Е. <8) и сохраняю промежуточные результаты в большом массиве. Использование <em>байтового массива (вместо массива int) быстрее (из-за попаданий в кэш). Но обширные броски байтов, распространяемые по коду, делают его гораздо более нечитабельным.

Ответы [ 16 ]

2 голосов
/ 06 июля 2009

Это, по большей части, мой ответ, относящийся к этой теме, который сначала был задан на аналогичный вопрос здесь .

Все операции с целыми числами, меньшими, чем Int32, округляются до 32 бит до вычисления по умолчанию. Причина, по которой результатом является Int32, заключается в том, чтобы просто оставить его как есть после расчета. Если вы проверяете арифметические коды операций MSIL, то единственными целыми числовыми типами, с которыми они работают, являются Int32 и Int64. Это "по замыслу".

Если вы хотите получить результат обратно в формате Int16, это не имеет значения, если вы выполняете приведение в коде, или компилятор (гипотетически) запускает преобразование «под капотом».

Например, для выполнения арифметики Int16:

short a = 2, b = 3;

short c = (short) (a + b);

Два числа будут расширены до 32 бит, добавлены, а затем усечены до 16 бит, как и предполагал MS.

Преимущество использования коротких (или байтовых) данных заключается, прежде всего, в хранении данных в тех случаях, когда у вас есть большие объемы данных (графические данные, потоковая передача и т. Д.)

1 голос
/ 01 ноября 2018

У меня есть тест производительности между байтом и целым числом.
Со значениями int:

class Program
{
    private int a,b,c,d,e,f;

    public Program()
    {
        a = 1;
        b = 2;
        c = (a + b);
        d = (a - b);
        e = (b / a);
        f = (c * b);
    }

    static void Main(string[] args)
    {
        int max = 10000000;
        DateTime start = DateTime.Now;
        Program[] tab = new Program[max];

        for (int i = 0; i < max; i++)
        {
            tab[i] = new Program();
        }
        DateTime stop = DateTime.Now;

        Debug.WriteLine(stop.Subtract(start).TotalSeconds);
    }
}

С байтовыми значениями:

class Program
{
    private byte a,b,c,d,e,f;

    public Program()
    {
        a = 1;
        b = 2;
        c = (byte)(a + b);
        d = (byte)(a - b);
        e = (byte)(b / a);
        f = (byte)(c * b);
    }

    static void Main(string[] args)
    {
        int max = 10000000;
        DateTime start = DateTime.Now;
        Program[] tab = new Program[max];

        for (int i = 0; i < max; i++)
        {
            tab[i] = new Program();
        }
        DateTime stop = DateTime.Now;

        Debug.WriteLine(stop.Subtract(start).TotalSeconds);
    }
}

Вот результат:
байт: 3,57 с 157 месяцев, 3,71 с 171 месяц, 3,74 с 168 месяцев с процессором ~ = 30%
int: 4,05 с 298 месяцев, 3,92 с 278 месяцев, 4,28 294 месяцев с процессором ~ = 27%
Вывод:
байт использует больше ресурсов процессора, но это стоит меньше памяти и быстрее (возможно, из-за того, что выделяется меньше байтов)

1 голос
/ 01 февраля 2010

Из кода .NET Framework:

// bytes
private static object AddByte(byte Left, byte Right)
{
    short num = (short) (Left + Right);
    if (num > 0xff)
    {
        return num;
    }
    return (byte) num;
}

// shorts (int16)
private static object AddInt16(short Left, short Right)
{
    int num = Left + Right;
    if ((num <= 0x7fff) && (num >= -32768))
    {
        return (short) num;
    }
    return num;
}

Упрощение с .NET 3.5 и выше:

public static class Extensions 
{
    public static byte Add(this byte a, byte b)
    {
        return (byte)(a + b);
    }
}

Теперь вы можете сделать:

byte a = 1, b = 2, c;
c = a.Add(b);

1 голос
/ 03 июня 2009

Добавление не определено для байтов. Поэтому они приводятся к int для дополнения. Это верно для большинства математических операций и байтов. (обратите внимание, что так было на старых языках, я полагаю, что это верно и сегодня).

1 голос
/ 03 июня 2009

Я думаю, что это проектное решение о том, какая операция была более распространенной ... Если byte + byte = byte, возможно, гораздо больше людей будет обеспокоено необходимостью приводить к int, когда в качестве результата требуется int.

0 голосов
/ 03 июня 2009

В дополнение ко всем другим замечательным комментариям, я подумал, что добавлю один маленький кусочек. Многие комментарии задавались вопросом, почему int, long и почти любой другой числовой тип также не следуют этому правилу ... возвращать «больший» тип в ответ на арифметику.

Многие ответы были связаны с производительностью (ну, 32 бита быстрее, чем 8 бит). На самом деле, 8-битное число по-прежнему 32-битное число для 32-битного ЦП .... даже если вы добавите два байта, кусок данных, на котором работает процессор, будет 32-битным независимо, поэтому добавление целых не будет Быть "быстрее", чем добавлять два байта ... это все равно для процессора. ТЕПЕРЬ, добавление двух целых будет БЫСТРЕЕ, чем добавление двух длинных на 32-битном процессоре, потому что добавление двух длинных требует больше микроопераций, так как вы работаете с числами шире, чем у процессоров.

Я думаю, что основная причина побуждения байтовой арифметики к целым числам довольно ясна и прямолинейна: 8 бит просто не идут очень далеко! : D С 8 битами у вас есть диапазон без знака 0-255. Это не много места для работы ... вероятность того, что вы столкнетесь с байтовыми ограничениями, ОЧЕНЬ высока при использовании их в арифметике. Однако вероятность того, что у вас закончатся биты при работе с целыми, длинными или двойными и т. Д., Значительно ниже ... настолько мала, что мы очень редко сталкиваемся с необходимостью большего.

Автоматическое преобразование из байта в int равно логично , потому что масштаб байта очень мал. Автоматическое преобразование из int в long, float в double и т. Д. Имеет значение не логично , поскольку эти числа имеют значительный масштаб.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...