Question

J'ai besoin du code d'un routeur qui est autorisé à déborder et où < > continuer à indiquer les valeurs antérieures à partir des valeurs ultérieures, pour un intervalle défini.

Pour clarifier, une implémentation possible serait:

Considérez deux de ces compteurs cur et dut (périphérique en cours de test), considérez deux fonctions:

bool isEarlier(cur, dut)    // Is dut earlier than cur?
bool isLater(cur, dut)

cur et dut ont 16 bits, cur vient de déborder, sa valeur actuelle est, disons 5 . En fonction de la valeur de dut , les fonctions renverraient

  • 0 à 16384: isEarlier - > (cur < dut) , isLater - > (cur > dut)
  • 16384 à 32768: isEarlier - > faux, est plus tard - > vrai
  • 32768 à 49152: non valide, erreur de journalisation
  • 49152 à 65536: isEarlier - > true, isLater - > faux

Je peux écrire le code moi-même, pas de problème. Je suis juste paresseux. Je sais pertinemment qu'il existe quelque chose comme ça dans PostgreSQL (identifiants de transaction), je ne pouvais tout simplement pas localiser la fonction qui le fait réellement. Je suis à peu près sûr qu'il y a quelque chose comme ça dans le noyau Linux, probablement une macro. Cependant, aucune autre recherche Google, ni grep over / usr / include / linux ne pourrait l’activer. Des idées où il est?

Clarification du rôle de cur et dut. Le " invalide " y at-il comme une sauvegarde. Lorsque les différences entre cur et dut deviennent plus grandes, la fonction se plaint finalement.

Était-ce utile?

La solution

Je pense que vous parlez de gérer correctement l'enveloppe du cercle de chiffres. C'est assez facile, en fait.

Cela ne fait pas exactement ce que vous avez dit (vous ne savez pas pourquoi vous avez cet intervalle "d'exception"), mais:

typedef unsigned short uint16_t;
typedef signed short int16_t;
// abstract out 16-bit types in case "short" doesn't correspond to 16bits

bool isEarlier(uint16_t a, uint16_t b)
{
   int16_t diff = a-b;
   return diff < 0;
}
bool isLater(uint16_t a, uint16_t b)
{
   int16_t diff = a-b;
   return diff > 0;
}

modifier : il comporte un "point de branchement". à diff = -32768, si bien que si a = 5 et b = 32772, diff = -32767, ce qui est inférieur à 0 et par conséquent, 5 est "antérieure" que 32772. Si a = 5 et b = 32774, diff = -32769 = 32767, ce qui est supérieur à 0 et donc 5 est "plus tard". que 32774. Ceci définit "plus tôt" et " plus tard " dans le sens de (a) le calcul le plus simple, et (b) étant donné que les compteurs enveloppants peuvent être interprétés comme ayant plusieurs solutions mod 65536, il choisit les solutions de a et b qui sont "les plus proches". les uns aux autres par rapport au cercle de nombres.

Si a et b diffèrent de 32768, ils sont également éloignés l'un de l'autre et le calcul simplifié sert à choisir le plus facile ... ceci "viole". la propriété antisymétrique de "plus tôt" et " plus tard " dans le sens où isLater (5.32773) est vrai et isLater (32773.5) est également vrai. Mais comment savoir si " 5 " représente un compte de 5 ou "5" représente un nombre de 65541? (tout comme abs (-32768) == -32768 donne une réponse étrange et absurde) Si vous souhaitez maintenir l'antisymétrie, par ex. isLater (b, a) == isEarlier (a, b), vous pouvez toujours le faire:

bool isLater(uint16_t a, uint16_t b)
{
   int16_t diff = b-a;
   return diff < 0;
}

Si vous souhaitez biaiser le point de branchement dans une direction pour qu'il se produise à -32768 + K, utilisez plutôt ceci:

bool isEarlier(uint16_t a, uint16_t b)
{
   int16_t diff = a-b-K;
   return diff < -K;
}
bool isLater(uint16_t a, uint16_t b)
{
   int16_t diff = b-a-K;
   return diff < -K;
}

Ceci n’utilise plus le plus proche; si, par exemple, K = 12768 et a = 5, alors pour b = 6,7,8,9, ... 20005, isEarlier (a, b) et isLater (b, a) seront vrais, et pour b = 20006, 20007, ... 65534, 65535, 0, 1, 2, 3, 4, 5 isEarlier (a, b) et isLater (b, a) seront faux.

Vous avez un choix particulier d'intervalles qui diffère de la logique que j'utilise avec les nombres enveloppants. Les fonctions définies ici ne répondraient pas à vos besoins comme indiqué, mais je trouve ces choix d'intervalle un peu particuliers. Peut-être pourriez-vous expliquer comment vous les avez déterminés?

Autres conseils

Calculez d'abord la différence, puis vérifiez dans quelle fenêtre elle se situe.

Comme c'est si simple et que la taille des fenêtres passées / futures / d'erreur varie, vous devez le faire vous-même.

Ok, pour mémoire. Voici ma solution, voici ce que je voulais dire:

#include <stdint.h>


void increase_cyclic_counter (uint16_t *cnt)
{
#ifdef CYCLIC_COUNTER_EXPLICIT_WRAP
    if (*cnt < 2^16-1)
        *cnt++;
    else
        *cnt = 0;
#else
    *cnt++;
#endif
}


#define SAME 1
#define LATER 0
#define EARLIER 2
#define FORBIDDEN -1

/* dut (device under test) is tested against cur
 * returns:
 *    EARLIER (LATER) if dut happened earlier (later) in the sequence than cur
 *    SAME            if dut == cur
 *    FORBIDDEN       if dut and cur are that far away in the cyclic sequence
 *                    that no unambigious jugement is possible
 *
 * The basic idea is the same as with two-character year codes, where 
 * '97' stands for 1997 and '11' stands for 2011. '50' is regarded as 
 * too ambigous and therefore rejected.
 *
 * The implementation splits the short integer range 0-65535 into 4 parts:
 *   0-16383, 16384-32767, 32768-49151, 49152-65536
 * With cur and dut in the same range, normal arithmetics apply, else the 
 * ranges are compared to each other.
 */

int test_cyclic_counter (uint16_t cur, uint16_t dut)
{
    switch (((int)(cur>>14)) - ((int)(dut>>14)))
    {
        case 0:  // same range
            if (dut < cur) 
                return EARLIER;
            else if (dut == cur)
                return SAME;
            else 
                return LATER;

        case 1:
        case -3:
            return EARLIER;

        case 3:
        case -1:        
            return LATER;

        default: 
            return FORBIDDEN;
    }
}

Il me semble que vous venez de l'écrire :). Pourquoi ne pas traduire votre message en code C?

N'oubliez pas que vous ne pouvez pas obtenir les "> "" et " " " faire ce que vous voulez en C. Ils s’appliquent uniquement aux nombres et il n’ya pas de surcharge de l’opérateur. La même chose s'applique à votre exception. C n'a pas d'exception.

Vous pourriez écrire certaines fonctions d'accès qui traiteraient les types intégraux non signés de cette façon, et cela ne serait pas difficile. (En C, le dépassement de capacité n'est pas défini pour les types intégraux signés, même s'il est généralement utilisé sur les systèmes modernes.) Cela ne serait pas si difficile.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top