[Fonctions]coder une date sur 32 bits

Répondre
Partager Rechercher
J'ai souvent besoin de stocker des dates dans des variables, pas seulement, l'heure, parce que je peux en avoir besoin plusieurs jours (ingame) plus tard, donc probleme avec les mois, donc les années, au final, j'ai besoin d'une date complète jj/mm/aa hh:mm
Je n'avais pas envie de transformer ça en string, parce que j'en ai marre des getleft getrigth etc. (que j'utilise bcp ailleurs ) donc :
sur un int ! mais évidement on peut pas additionner comme ça, et si on stock genre les minutes sur les deux premiers chiffres, les heures sur les deux suivants, etc.
on dépasse 2^32 le maximum du type entier

ça ne servira peut être à personne, mais ça m'a amusé, alors je met ça là.

Y a la liste des fonctions et leur utilisation plus bas.

liens :
ici le fichier direct
dans cette page, le fichier bitdate.erf (la page est sommaire, mais elle est là pour ca )


Comment c'est fait :
pas forcement au mieux :]
petit rappel, pour le binaire, le bit numéro i correspond à : 2^(i-1)
autrement dit quand on a une suite (ak) de 0 et de 1 où a0 est la valeur du bit 0, l'entier en base 10 est :
n = a0 * 2^0 + a1 * 2^1 + a2 * 2^2 + . . .
donc
0 -> 0
1 -> 1
2 -> 10
3 -> 11
4 -> 100
etc.

donc, on "optimise" la transformation en un unique entier

minutes : maximum 60 < 2^6 stockable sur 6 bits
heure : 24 < 2^5 stockable sur 5 bits
jour : 28 < 2^5 stockable sur 5 bits
mois : 12 < 2^4 stockable sur 4 bits
année : 2047 < 2^11 stockable sur 11 bits

j'ai limité les années, à 2047, parce que j'ai pas besoin de plus, mais il faut pas grd chose pour aller plus loin, rajouter un int ou bien commencer non pas à partir de l'an 0 (qui ne sert à rien) mais de l'an 2047 par exemple

bref, ça rentre sur 32 bits, donc voila

le principe :
on stocke les nombres (année, mois, etc.) sur des bits bien précis (minutes : 6 premiers, heures 5 suivant, etc.)
par exemple, quand on a les données de la date, pour avoir une date stockée sur 32 bits :

Code PHP:

bitDate nminutes;
bitdate bitDate + (nheure << 6);
bitdate bitDate + (njour << (6+5));
bitdate bitDate + (nmois << (6+5+5));
bitdate bitDate + (nannee << (6+5+5+4)); 
l'opérateur ( x << n) décale l'entier x de n bits sur la gauche (les bits de poids faibles sont à droite)

vous suivez toujours ? (pas que ça soit dur, mais si c'est la première fois qu'on le voit, ça peut dérouter )

donc pour revenir :
on doit d'abord sélectionner les bits qui nous intéressent. Pour cela on utilise l'opérateur binaire & (et) (l'operateur passe mal dans le message, il n'y a pas de "amp" derrière normalement mais en html . . . )
si n1 et n2 sont notés en base 2 :
n1 & n2 renvoi un nombre en binaire tels qu'un bit vaut 1 si il vaut 1 pour n1 ET n2, donc
Code PHP:

11001100111 11111000000 11001000000 

on a selectionné les 5 premiers bits du nb de gauche
il ne reste plus qu'a faire
Code PHP:

11001100111 >> 11001 

on a récupéré l'heure

ces operations marchent pareil avec des entiers tels qu'on les "voit" dans le nwscript (en base 10), vu qu'ils sont stockés en binaire en gros (vu l'architecture des pcs c'est d'ailleurs pour ça aussi la limite à 2^32, rapport aux procs (les athlon 64 et consorts son récents qd même :] fin, c'est ce que je comprend, et j'y connais pas vraiment grand chose ^_^ )


Tout ça c'est bien joli, mais Comment ça s'utilise :
Comprendre ce qu'il y a au dessus ne sert à rien (c'est marrant, c'est tout).
Comprendre ce qu'il y a au dessous peut servir.

liste des fonctions :
Code PHP:

int BDGetDateToBit();
int BDSoustraitDate(int nDateint nDureeint bBitdate TRUE);
int BDAjouteDate(int nDateint nDureeint bBitdate TRUE);
int BDMinuteFromBitdate(int nbd);
int BDHeureFromBitdate(int nbd);
int BDJourFromBitdate(int nbd);
int BDMoisFromBitdate(int nbd);
int BDAnneeFromBitdate(int nbd);
int BDVraiMinuteToBit(int nMinute);
int BDHeureToBit(int nHeure);
int BDJourToBit(int nJour);
int BDMoisToBit(int nMois);
int BDAnneeToBit(int nAnnee);
int BDDateToMinute(int nDate); 
Je m'excuse pour l'orthographe désastreuse, mais non seulement je ne suis pas aidé de ce coté, mais en plus j'ai tendance à m'en battre les steaks quand je script

Bref, donc.
Il y a un tout petit problème : la différence entre une durée en une date. En effet, on a un mois numéro 12 mais on ne dit pas "rendez vous dans 12 mois" mais "rendez vous dans un ans" donc, on doit faire attention quand on veut convertir ou quand on souhaite additionner ou soustraire
Le problème ne se pose ni avec les minutes ni avec les heures.


BDGetDateToBit
Renvoi la date courante du module, codée avec 32 bits.


Les autres fonctions BD____ToBit
Elles permettent de transformer un entier en ce qui le code sur 32 bits.
Ainsi BDMoisToBit(nMois) renvoi le code de nMois en 32 bits, soit 16 bits "blancs" (à 0 ) puis nMois

Pour obtenir une date, il suffit d'additionner le résultats des fonctions :
Code PHP:

bitDate 12;//minute
bitDate bitDate BDHeureToBit(5);//heure
bitDate bitDate BDJourToBit(11);//jour
bitDate bitDate BDMoisToBit(5);//mois
bitDate bitDate BDAnneeToBit(1373);//année 
stock dans bitDate le 11/5/1373 5h12

Code PHP:

bitDuree12;//minute
bitDureebitDureeBDJourToBit(27);//jour
bitDureebitDureeBDMoisToBit(5);//mois 
stock dans bitDuree 5 mois 27 jours et 12 minutes
rq :
pour le problème de la différence durée/date
les fonction pour le mois le jour l'année n'en tiennent pas compte, autrement dit on peut leur entrer ce qu'on vet, 0 mois, 12 mois, etc.
il convient donc de faire attention à ce qu'on manie, et ne pas croire obtenir une date avec BDMoisToBit(0) ou une durée avec BDMoisToBit(12)

Pour toutes les fonctions il faut faire attention à ne pas dépasser le maximum, elles sont très simple et se contente de transcrire bêtement, ainsi si on entre 36 heures on va avoir des problèmes quand on souhaitera utiliser le chiffre renvoyé avec d'autres.
Je n'ai pas fais la conversion dans les fonction (36 heures devenant 1 jour et 12 heures) parce que euh , sur le coup ça ne m'interessait pas. Cela dit ce ne devrait pas être très compliqué mais bon -_-


BDVraiMinuteToBit
Renvoi nMinute codees sur les 32 bits d'une date
les minutes sont en temps reel, ne tiennent donc pas du reglage minutes/heure du module
le codage de minutes qui tiendrait compte de ce rglage est simple, puisqu'il n'y a rien faire
cad : reglage du module : 10min/heures
je souhaite coder une demi heure
pour creer une bitdate
je peux utiliser BDVraiMinuteToBit(30)
ou directement 5
!!! renvoi une duree ou une date celon ce qu'on lui entre
ex : on peut obtenir une duree (une date "non valide" comme 128 minutes)
en entrant 128, cette duree sera codee de facon a
etre additionnable (ou soustrayable) a une bidate
(avec la fonction appropriee : BDSoustrait ou BDAjoute )


Les fonctions BD____FromBitdate :
Elles prennent en argument une date crée avec les fonctions précédentes, elles renvoient ce qu'il y a dans leur nom :]
Ces fonctions sont elles aussi très simples, elles peuvent donc renvoyer une date ou une durée celon comment a été codée la date
ex :
0 (durée) ou 28 (date) jours


Operations sur des dates/durée :
En dehors de la simple "création" d'une date ou d'une durée ou un simple + suffit, si l'on veut obtenir la date qui vient 1 an 3 jours 6 heures après une autre, il faut utiliser
Code PHP:

int BDAjouteDate(int nDateint nDureeint bBitdate TRUE); 

si bBitdate vaut TRUE le résultat renvoi une date valide (jour 28 et non pas 0 jours), sinon, il renvoi une durée (1 mois et non pas 28 jours) (si l'on additionne deux durée par exemple)

Pour une soustraction, on utilise de la même manière
Code PHP:

int BDSoustraitDate(int nDateint nDureeint bBitdate TRUE); 

Ces fonctions sont pas optimisées, il était tard quand je les ai faites, donc je refait la division euclidienne alors que % et / sont là pour ça -_-
Mais ça change aps grand chose, et sera changé bientot

BDDateToMinute
renvoi simplement le nombre de minutes dans une bitDate
Utile pour transformer une durée en minutes par exemple, pour utiliser dans un Delay (en multipliant par 60)

rqs :
Beaucoup de bruit pour pas grand chose

Je compte bientot ajouter deux trois trucs, comme une fonction qui traduit les nombres dans le calendrier commun des Royaumes et faire plus gaffe dans les fonctions BD_____ToBit.
Mais en l'état ça marche très bien (tests à l'appui) et ça ne sera pas avant ce week end.
De toutes façons l'utilisation des fonctions et leurs noms (et paramètres) ne seront pas modifiés, donc ce qui est écrit avec maintenant marchera toujours.

ça n'est pas forcement utile (jouer avec plusieurs entiers ou avec une string marcherais aussi bien) mais là, c'est plus drôle

Le fichiers est largement commenté pour ceux que ça interesse, mal écrit et pas forcement très claire, mais commenté.

Si vous avez des questions, posez-les , je passe de temps ici, et il m'arrive de relever le courrier au pire >_<

L'idée m'est venue (en recherchant un moyen de stocker ces fichus dates) en retombant sur un vieux fichier sur mon dur, le sujet où il était question du stockage de 31 booléens sur un unique entier (la grande époque, avec Azra, Jaha, Jedai et d'autres rescapés/fantomes *soupir* )
La recherche est désactivée, donc je n'ai pas l'adresse sous la main, mais l'idée était terrible (et la mise en oeuvre éclairante)
__________________
scripteur à mi-temps amateur brouillon flemmard
et pas si compétent, encore un scienteux
qui ne sait aligner deux mots correctement

quelques messages d'erreurs classiques
han

c'est sur, ca marche aussi, mais c'est pas grave, c'est moins drole fait comme ca ^_^
/me préfère son paté de nouille écrasé au rouleau compresseur

et puis de toutes façons, faut bien se taper les operations avé retenues donc bon.
et puis comme ca j'aurais joué avec les bitbidules
et puis ouais, j'y avais pensé faut pas croire>_<
__________________
scripteur à mi-temps amateur brouillon flemmard
et pas si compétent, encore un scienteux
qui ne sait aligner deux mots correctement

quelques messages d'erreurs classiques
humhum.... comment q'y disaient déjà dans BG1 .....

Citation :
"un gaspillage de talent"


enfin je suis ravi de voir que mes petits délires fanatiques puisse encore trouver des adeptes parmis cette jeunesse si terre à terre
tu es sur le bon chemin pour me dépasser parmis les scripts les plus dingues (et les plus inutiles) de Maskado !!!

tient pendant qu'on y est, quelqu'un est il interessé par un mix préprocesseur C / nwscript compatible linux ?
Citation :
Publié par Sherazade
Pour ma part, pour encoder une date je fais plus simple : Date = AA*12*28*24 + MM*28*24 + JJ*24 + H.

Et décodage inverse pour récupérer les constituants.
Peux-tu/pouvez-vous expliquez ça au noob que je suis ?
Il écrit la date sous forme d'heures.

Tout le monde sait que (sur terre en tout cas ) 1jour = 24heure, un mois = de 28 à 31 (et fixé à 28 sous NWN) jours, et un an = 12mois

on peut donc écrire une date via la formule :
Citation :
Date = AA*12*28*24 + MM*28*24 + JJ*24 + H
avec AA l'année courante, MM le mois courant, JJ le jour, et H l'heure

pour récupérer chacun des éléments, c'est relativement facile (sauf erreur de ma part ):

H = Date % 24
JJ = (Date / 24) % 28
MM = (Date / (24 * 28)) % 12
AA = Date / (24 * 28 * 12)
(on peut aussi optimiser si on récupère toutes les infos dans le même temps)

Le % est le "modulo" mathématique, soit le reste d'une division euclidienne( 9 / 2 = 4 et 9 % 2 = 1)

on peut bien entendu retenir également les minutes et les secondes en rajoutant des échelles, jusqu'à un maximum de 2^16 unités (ou 2^32 si on compte dans le négatif aussi :P)
*hoche pensivement la tête*
*n'est pas sur d'avoir tout saisi clairement, mais sent un neurone de compréhension germer*

Euraka !
Date = le nmb d'heures après la naissance du Xrist...

*reste fasciné par cette histoire de modulo, sont forts ces matheux*

Merci pour le développement

Red
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés