Funkcja zwracająca tylko 1 bit

0

Mam funkcję, która zwraca tylko jeden bit:

static __uint128_t x = 0, weyl = 0, s = 1;

bool next(void)
{
  x = (-(x & 1) & (x + ((x + 1) >> 1)) | ~-(x & 1) & (x >> 1)) ^ (weyl += s);
  return x & 1;
}

Czy taka funkcja powinna być zdefiniowana jako bool, czy jakoś inaczej? Teoretycznie mogłaby zwracać jakiegokolwiek inta, ale skoro zwraca tylko jeden bit, to chciałem użyć zmiennej, która przechowuje tylko jeden bit. Ale bool zwykle się odnosi do wartości true lub false, a nie 0 lub 1. Więc nie jestem pewien, czy to jest napisane zgodnie ze standardami.

0

A jaką wartość zwraca sizeof jak użyjesz na typie boolean? Chcesz zwrócić 1 bit to rób char'a (tablica 8 bitów) i zapisuj jeden z nich. 7 zostanie Ci zapasu.

4
Tomasz_D napisał(a):

. Ale bool zwykle się odnosi do wartości true lub false, a nie 0 lub 1. Więc nie jestem pewien, czy to jest napisane zgodnie ze standardami.

Standardami rozsądku czy standardami C ?
Bo to rozbieżne. W żadnym innym rozsądnym języku z funkcji bool nie mógłbyś zwrócić wyrażenia int/unsigned return x & 1;

Czym się motywujesz do tak postawionego zadania ?
Koszt czy ortodoksyjność zapisu ?

Najmniejsza jednostką adresowalną jest bajt, i nie ma mniej kosztownych operacji ani w sensie RAM, ani CPU *) (może na jakiś skrajnie małych mikrokontrolerach jest inna konwecnja wywołania/returnu, przypuszczenie).
Na ortodoksyjny bit pomocna by była struktura bitowa, ale to może być bardziej kosztowne.

C/C++ nie ma, ale są/były języki, które miały zawężenia typów np integerowych, np (chyba) w Pascalu dało by się stworzyć nowy typ integerowy 0..1 (oczywiście implementowany w bajcie czy słowie, cudów nie ma)
Języki posiadają enum'y, dobre do wyrażania tak małych zbiorów wartości, ale w C/C++ znów to jest spieprzone bo kompatybilne z integerem. Jak mawiał Kuraś, jak się nie ruszysz d. z tyłu.

*) na współczesnych super-duper-procesorach bajt jak masz pecha może dawać większe koszty CPU niż słowo.

4

nie da się w C++ zwrócić tylko jednego bita bo najmniejszy kawałek pamięci jaki można zaadresować na normalnym kompie to 1 bajt. Dlatego w bool zajmuje tyle samo co char

0
AnyKtokolwiek napisał(a):
Tomasz_D napisał(a):

. Ale bool zwykle się odnosi do wartości true lub false, a nie 0 lub 1. Więc nie jestem pewien, czy to jest napisane zgodnie ze standardami.

Standardami rozsądku czy standardami C ?
Bo to rozbieżne. W żadnym innym rozsądnym języku z funkcji bool nie mógłbyś zwrócić wyrażenia int/unsigned return x & 1;

Czym się motywujesz do tak postawionego zadania ?
Koszt czy ortodoksyjność zapisu ?

To jest generator liczb pseudolosowych, więc koszt, jeśli pytasz o koszt obliczeniowy, jest ważny. Z drugiej strony nikt nie będzie tego raczej używał do zwracania 1 bitu, tylko np. w pętli sklejającej to w jakieś inty (przynajmniej ja tego tak używałem). Ale w tym przypadku to jest po prostu przykład generatora zwracającego 1 bit za każdym razem, a jak ktoś sobie później tego użyje, to już jego sprawa. Ortodoksyjność jest ważna, bo kod ma iść do publikacji, więc dobrze, żeby ktoś się nie złapał za głowę, myśląc co tu się odwaliło.

1

@Tomasz_D:

To wydajnościowo nic nie poprawi, a ortodoksja dla każdego czytelnika C/C++ jest akceptowalna

Jaki jest SENS tego zwracanego bita, naprawdę logiczny czy jednak mała liczba ?
edit: czyli sugestia typu integerowego

0
AnyKtokolwiek napisał(a):

@Tomasz_D:

To wydajnościowo nic nie poprawi, a ortodoksja dla każdego czytelnika C/C++ jest akceptowalna

Jaki jest SENS tego zwracanego bita, naprawdę logiczny czy jednak mała liczba ?

Chodzi o liczbę. Generator generuje strumień bitów i można je zaaranżować np. w 32-bitowe liczby:

static __uint128_t x = 0, weyl = 0, s = 1;
static uint32_t v = 0;

uint32_t next(void)
{
    for (int i = 0; i < 32; i++)
        {
        x = (-(x & 1) & (x + ((x + 1) >> 1)) | ~-(x & 1) & (x >> 1)) ^ (weyl += s);
        v += (x & 1) << i;
        }
    return v;
}

Ale oczywiście to nie ma znaczenia jak ktoś tego strumienia bitów użyje, czy jako zaledwie liczby 0 lub 1, czy połączy je w liczby 8-bitowe, czy jeszcze inne, np. 32-bitowe jak w przykładzie.

Jeśli ortodoksja jest akceptowalna, to tyle chciałem wiedzieć.

0

@Tomasz_D:

Myśl przy kawie ... W wariancie "top speed" i C++ bym mógł sobie wyobrazić jakąś klasę, generowanie większej ilosci bitów (8/16/32), to enkapsulowane (prywatne) i jakiś bardzo szybki public akcesor do kolejnego bitu

Dla mnie to by było ortodoksyjnym C++, bo na razie to C.

2

Używanie bit-ów ma większy sens jak procesor pozwala na tego typu operacje np. mikro-kontrolery z rodziny 8051
https://stackoverflow.com/a/10082501
kompilatory np:

  • SDCC (Small Device C Compiler)
  • https://www.keil.com/
  • i był jeszcze kiedyś jakiś kompilator pascalowy na 51 ale już nazwy nie pamiętam
2
AnyKtokolwiek napisał(a):

Najmniejsza jednostką adresowalną jest bajt, i nie ma mniej kosztownych operacji ani w sensie RAM, ani CPU *)

O ile dobrze pamiętam, to na x86_64 operacje na 64bitach są wydajniejsze niż na bajcie. Możliwe też że taka instrukcja zajmuje mniej pamięci. A na pewno operacje na adresach podzielnych przez 8, w związku z czym użycie typu o większym rozmiarze może być szybsze kosztem pamięci. Przy czym w strukturze, bardzo prawdopodobne, że kompilator sam doda nieużywane bajty żeby wszystkie pola były na takich adresach.

2

Najmniejsza jednostką adresowalną jest bajt, i nie ma mniej kosztownych operacji ani w sensie RAM, ani CPU *) (może na jakiś skrajnie małych mikrokontrolerach jest inna konwecnja wywołania/returnu, przypuszczenie).

Gdyby pisać w asemblerze, do zwracania pojedynczego bitu można wykorzystywać flagi procesora, i to się sprawdza jeśli od razu chcemy zareagować na konkretny stan danej flagi (czyli – używając terminów wyższego poziomu – od razu po wywołaniu funkcji mamy jakiś if na zwracanej wartości, i nie potrzebujemy już więcej tej wartości). Jest z tym jednak kilka problemów:
– różne instrukcje procesora nadpisują stan różnych flag, dlatego flagi trzeba traktować jako mocno ulotne,
– zapamiętanie takiej flagi w RAM-ie siłą rzeczy zajmie co najmniej jeden bajt,
– nie ma bezpośredniego dostępu do flag procesora w językach wysokiego poziomu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1