Что лучший способ состоит в том, чтобы объединить две единицы в ulong в c#

Строки @Mendelt Siebenga

являются ключевыми объектами на языках программирования. Различные языки реализуют строки по-другому. Реализация join() сильно зависит от конкретной реализации строк. Псевдокод не отражает конкретную реализацию.

Рассматривают join() в Python. Это может легко использоваться:

print ", ".join(["Alpha", "Beta", "Gamma"])
# Alpha, Beta, Gamma

Это могло быть легко реализовано следующим образом:

def join(seq, sep=" "):
    if not seq:         return ""
    elif len(seq) == 1: return seq[0]
    return reduce(lambda x, y: x + sep + y, seq)

print join(["Alpha", "Beta", "Gamma"], ", ")
# Alpha, Beta, Gamma

И здесь как join() метод реализован в C (взятый от соединительная линия ):

PyDoc_STRVAR(join__doc__,
"S.join(sequence) -> string\n\
\n\
Return a string which is the concatenation of the strings in the\n\
sequence.  The separator between elements is S.");

static PyObject *
string_join(PyStringObject *self, PyObject *orig)
{
    char *sep = PyString_AS_STRING(self);
    const Py_ssize_t seplen = PyString_GET_SIZE(self);
    PyObject *res = NULL;
    char *p;
    Py_ssize_t seqlen = 0;
    size_t sz = 0;
    Py_ssize_t i;
    PyObject *seq, *item;

    seq = PySequence_Fast(orig, "");
    if (seq == NULL) {
        return NULL;
    }

    seqlen = PySequence_Size(seq);
    if (seqlen == 0) {
        Py_DECREF(seq);
        return PyString_FromString("");
    }
    if (seqlen == 1) {
        item = PySequence_Fast_GET_ITEM(seq, 0);
        if (PyString_CheckExact(item) || PyUnicode_CheckExact(item)) {
            Py_INCREF(item);
            Py_DECREF(seq);
            return item;
        }
    }

    /* There are at least two things to join, or else we have a subclass
     * of the builtin types in the sequence.
     * Do a pre-pass to figure out the total amount of space we'll
     * need (sz), see whether any argument is absurd, and defer to
     * the Unicode join if appropriate.
     */
    for (i = 0; i < seqlen; i++) {
        const size_t old_sz = sz;
        item = PySequence_Fast_GET_ITEM(seq, i);
        if (!PyString_Check(item)){
#ifdef Py_USING_UNICODE
            if (PyUnicode_Check(item)) {
                /* Defer to Unicode join.
                 * CAUTION:  There's no gurantee that the
                 * original sequence can be iterated over
                 * again, so we must pass seq here.
                 */
                PyObject *result;
                result = PyUnicode_Join((PyObject *)self, seq);
                Py_DECREF(seq);
                return result;
            }
#endif
            PyErr_Format(PyExc_TypeError,
                     "sequence item %zd: expected string,"
                     " %.80s found",
                     i, Py_TYPE(item)->tp_name);
            Py_DECREF(seq);
            return NULL;
        }
        sz += PyString_GET_SIZE(item);
        if (i != 0)
            sz += seplen;
        if (sz < old_sz || sz > PY_SSIZE_T_MAX) {
            PyErr_SetString(PyExc_OverflowError,
                "join() result is too long for a Python string");
            Py_DECREF(seq);
            return NULL;
        }
    }

    /* Allocate result space. */
    res = PyString_FromStringAndSize((char*)NULL, sz);
    if (res == NULL) {
        Py_DECREF(seq);
        return NULL;
    }

    /* Catenate everything. */
    p = PyString_AS_STRING(res);
    for (i = 0; i < seqlen; ++i) {
        size_t n;
        item = PySequence_Fast_GET_ITEM(seq, i);
        n = PyString_GET_SIZE(item);
        Py_MEMCPY(p, PyString_AS_STRING(item), n);
        p += n;
        if (i < seqlen - 1) {
            Py_MEMCPY(p, sep, seplen);
            p += seplen;
        }
    }

    Py_DECREF(seq);
    return res;
}

Примечание, что вышеупомянутой Catenate everything. код является небольшая часть целой функции.

В псевдокоде:

/* Catenate everything. */
for each item in sequence
    copy-assign item
    if not last item
        copy-assign separator

9
задан Jon Seigel 3 May 2010 в 02:54
поделиться

4 ответа

ulong mixed = (ulong)high << 32 | low;

Актерский состав очень важен. Если вы опустите приведение, учитывая тот факт, что high имеет тип uint (то есть 32 бита), вы сместите 32-битное значение на 32 бита влево. Операторы сдвига для 32-битных переменных будут использовать сдвиг по правой стороне по модулю 32. Фактически, сдвиг uint 32 бита влево не является -op . Преобразование в ulong предотвращает это.

Проверить этот факт легко:

uint test = 1u;
Console.WriteLine(test << 32); // prints 1
Console.WriteLine((ulong)test << 32); // prints (ulong)uint.MaxValue + 1
19
ответ дан 4 December 2019 в 09:14
поделиться

Вы должны преобразовать highInt в ulong, прежде чем выполнять битовый сдвиг:

ulong output = highInt;
output = output << 32;
output += lowInt;
1
ответ дан 4 December 2019 в 09:14
поделиться
ulong output = (ulong)highUInt << 32 + lowUInt

Операторы << и >> сдвигают бит влево (вверх) и вправо (вниз) соответственно. highUInt << 32 функционально совпадает с highUInt * Math.Pow (2, 32) , но может быть быстрее и имеет (IMO) более простой синтаксис.

2
ответ дан 4 December 2019 в 09:14
поделиться

Кодировка:

ulong mixed = (ulong)hi << 32 | lo;

Декодирование:

uint lo = (uint)(mixed & uint.MaxValue);
uint hi = (uint)(mixed >> 32);
1
ответ дан 4 December 2019 в 09:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: