|
Publicité ' | |||||||||||||||||||||||
|
|
#1 |
|
Membre Expert
![]() Inscription : octobre 2007 Messages : 3 947 ![]() |
Bonjour
Je suis confronté a un problème d'arrondi Je ne sais pas si le probleme vient du type de données ou de conversion Dans une table j'ai deux float 223,92 97,76 Je lis ces float en Csharp / ADO Je retrouve bien deux float Csharp : 223,92 et 97,76 Je resauve ces données dans une autre table et voici ce que j'obtiens ! Est-il possible d'eviter cela ? QT TpUnite PrixNet 223,919998168945 M2 9,76000022888184 Merci de votre aide
__________________
« Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain) |
|
|
00
|
|
|
#2 |
![]() ![]() ![]() Nicolas SouquetAdministrateur de base de données Inscription : janvier 2005 Messages : 4 669 ![]() |
Bonjour,
Je soupçonne fort une différence de mantisse entre le type float de C# et le type float de SQL Server. Regardez la table suivante : je crois qu'il faudrait que vous utilisiez un Double en C# ... Notons au passage que le type de données float de SQL Server n'est pas un type de données précis. Il vaut mieux donc utiliser le type numeric ou decimal. En revanche je ne comprend pas d'où vient la différence entre 97,76 et 9,76000022888184 (divisé par un peu plus 10 ?) @++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes. Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012 |
|
00
|
|
|
#3 | |
|
Membre Expert
![]() Inscription : octobre 2007 Messages : 3 947 ![]() |
Citation:
Merci Elsuket et merci pour ce tableau, Je vais travailler en double dans C#
__________________
« Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain) |
|
|
|
00
|
|
|
#4 |
![]() ![]() ![]() Nicolas SouquetAdministrateur de base de données Inscription : janvier 2005 Messages : 4 669 ![]() |
A votre place :
- Je changerai le type des deux colonnes vers numeric ou decimal : une quantité et un prix sont des valeurs précises - Je changerai le type de données C# en conséquence pour utiliser Decimal, comme indiqué par la table @++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes. Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012 |
|
00
|
|
|
#5 | ||
![]() ![]() ![]() Frédéric BROUARDExpert SGBDR & SQL Inscription : mai 2002 Messages : 10 954 ![]() |
Citation:
Citation:
A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/ Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp. Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation * * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * * |
||
|
00
|
|
|
#6 | |
![]() ![]() ![]() Frédéric BROUARDExpert SGBDR & SQL Inscription : mai 2002 Messages : 10 954 ![]() |
Citation:
Par exemple si la "quantité" est au litre ou au poids et que vous achetez de l'or ou du safran, les décimales feront toutes la différence !!!!! A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/ Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp. Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation * * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * * |
|
|
00
|
|
|
#7 | |||||||||
|
Membre éprouvé
![]() ![]() Hamid MIRAIngénieur développement logiciels Inscription : septembre 2003 Messages : 177 ![]() |
Citation:
Code :
Code :
Code :
Autre chose, transformer un type float en décimal est légitime et cela peut être un bon choix en rapport avec l’utilisation que vous en faites, mais attention, ce n'est pas transparent pour votre application. Je veux dire que ce n'est pas anodin et que cela peut générer des erreurs et des régressions dans votre application. Exemple : Code :
Msg*8115, Niveau*16, État*8, Ligne*4 Une erreur de dépassement arithmétique s'est produite lors de la conversion de numeric en type de données numeric. alors qu'en utilisant le type float le programme ne générait aucune erreur ! A+ |
|||||||||
|
|
10
|
|
|
#8 |
|
Membre Expert
![]() Inscription : octobre 2007 Messages : 3 947 ![]() |
Bon !
Et bien merci pour ces enseignement ! je vais donc maintenant me battre pour essayer de trouver la meilleure combinaison possible afin de stocker en DB des quantité a 4 décimale et des valeurs a deux decimales et manipuler celles ci correctement en C# Ca ne semble hélas pas trivial mais d'apres ce que je comprends le bon choix serait peut etre de travailler en Decimal des deux cotés (Sql Server et C#) Personnelement je n'ai jamais travaillé en Décimal qui me semblait un type batard par raport au double ou au float !
__________________
« Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain) |
|
|
00
|
|
|
#9 |
![]() ![]() ![]() Nicolas SouquetAdministrateur de base de données Inscription : janvier 2005 Messages : 4 669 ![]() |
Pour ma part je n'utilise ni float (aucun calcul scientifique dans l'application sur laquelle je travaille) et surtout jamais le pseudo-type money, qui lui par contre produit des erreurs de calcul bien connues.
@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes. Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012 |
|
00
|
|
|
#10 |
|
Membre Expert
![]() Inscription : octobre 2007 Messages : 3 947 ![]() |
Bonjour Elsuket
Effectivement j'avais déja constaté que Money est a proscrire Par contre quand je suis en C# j'utilise généralement les doubles Que me conseillerais tu en définitive pour assurer un bon dialogue avec SQL Server ? decimal partout ?
__________________
« Ils ne savaient pas que c'était impossible, alors ils l'ont fait ». (Twain) |
|
|
00
|
|
|
#11 | ||||||||
![]() ![]() ![]() Nicolas SouquetAdministrateur de base de données Inscription : janvier 2005 Messages : 4 669 ![]() |
Désolé de ma réponse très tardive, mais je me dois de revenir là-dessus :
Citation:
La définition qui en est donnée est la suivante : Citation:
Code :
Donc on vient de perdre une précision qui peut s'avérer non négligeable dans des calculs, quels qu'ils soient. Second exemple : Citation:
Citation:
Or, l'addition est commutative, donc mathématiquement, ce résultat est faux. Ensuite, votre démonstration est fausse sur ce point : si je fais un SELECT @decimal3, j'obtiens 2071.42857142857142857. En le stockant dans un decimal(12,4) vous perdez de la précision en ne stockant que les 4 premières décimales. Ce qui explique par la suite que votre résultat soit "faux". Si je reprends votre exemple en changeant la précision et l'échelle pour "contenir" les calculs : Code :
Donc encore une fois, le choix du type de données approprié non seulement au stockage de la donnée et aux calculs que l'on peut effectuer sur ces valeurs ne doit jamais être négligé. @++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes. Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012 |
||||||||
|
10
|
|
|
#12 |
|
Membre éprouvé
![]() ![]() Hamid MIRAIngénieur développement logiciels Inscription : septembre 2003 Messages : 177 ![]() |
Merci beaucoup Elsuket pour ce retour d'information, et tes investigations sur le sujet. Les exemples que tu donnes ne sont pas dénoués d'intérêts. Ils sont très intéressants.
Le premier exemple peut être effectivement déroutant pour le développeur qui voit ainsi s'évaporer par magie plusieurs chiffre de précision ! Pour revenir à mon exemple. Il ne s'agit pas d'une erreur de ma part. J'avais bien vu qu'en augmentant la précision on allait retomber sur ses pieds. J'ai gardé exprès cet exemple pour montrer un cas d'utilisation où le float donne un résultat plus précis (ou plus juste) que le type décimal. En effet, on ne peut pas toujours ajuster la précision au cas par cas ! Il y a des situations où l'utilisation du type Float s'avère incontournable, notamment lorsqu'on ne connait pas à l'avance l'ordre de grandeur. (exemple une table représentant les distances séparant des « entités » (nanoparticules, atomes, villes, étoiles, etc..). dans ce cas les distances peuvent varier de l’infiniment petit à l’infiniment grand. et dans ce contexte, l'utilisation du type décimal serait impossible et le type Float serait le plus approprié. J'ai réétudié la question et fini par établi mes propres conclusions sur le sujet, conclusions que je vous livre : - Le type decimal un bon choix, et est approprié pour représenter les montants dont on connait l'ordre de grandeur et la précision souhaitée. - Les types de données float (ou real) présentant un caractère approximatif, ne doivent pas être utilisées lorsqu'un comportement numérique exact est requis, comme dans les applications financières, les opérations comprenant des arrondis ou les vérifications d'égalité. Il faut utiliser, en lieu et place, en fonction de la nature de l'information, les types de données comme integer, decimal, money ou smallmoney, etc.. (extrait de http://msdn.microsoft.com/fr-fr/library/ms187912.aspx) - Le type float doit être réservé au calcul scientifique. Le type Float est approprié lorsque veut représenter un très large éventail de valeur allant de l’infiniment petit à l’infiniment grand, c.à.d pour représenter les nombre réels au sens mathématique du terme. - Le type Float SQL Server s'approche de la norme IEEE 754 (mais ne respecte pas complétement la norme IEEE 754). En effet, ni la valeur NaN (Not-a-Number,), ni l'infinie ne peuvent être représentés. Toute tentative de conversion d'une chaîne non numérique en type numérique et de division par zéro entraîne une erreur. Beaucoup de développeurs n'avaient pas d'autres choix, et ont fini par représenter les NaN et l'infini par des valeur NULL. (Pour plus de détails, voir : http://msdn.microsoft.com/fr-fr/library/ms172002.aspx) - Il faut évitez d'utiliser les colonnes de type float (ou real) dans les clause WHERE, plus particulièrement les opérateurs = et <>. L'idéal est de limiter les colonnes float et real aux signes de comparaison > ou <. A+ |
|
|
00
|
|
|
#13 | |
![]() ![]() ![]() Nicolas SouquetAdministrateur de base de données Inscription : janvier 2005 Messages : 4 669 ![]() |
Merci pour ces références.
Citation:
Vous auriez du avoir une entité nanoparticule, une autre atome, une autre ville, un autre étoile, etc ... Vous pouvez dans ce cas utiliser la spécialisation, c'est à dire créer une entité dont tous les attributs sont communs à chacune de celles qui constituent votre liste, et dans chaque entité, ajouter seulement les attributs qui sont particuliers à celles-ci. Chaque entité référence l'entité "mère" D'autre part je pense que la mantisse de 38 chiffres significatifs est suffisante de très petites comme de très grandes distances. @++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes. Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012 |
|
|
00
|
|
|
#14 | ||||||||||||
|
Membre éprouvé
![]() ![]() Hamid MIRAIngénieur développement logiciels Inscription : septembre 2003 Messages : 177 ![]() |
Ce n'est pas un problème de conception ! C'est un problème de « domaine », au sens relationnel du terme ; c.à.d. l’ensemble dans lequel les données d'un attribut (ie une colonne d'une relation) prennent valeur.
Le domaine Float, est défini par intention : Float (n) ensemble des nombres en virgule flottante codé sur 32 bits (soit 4 octets) si n <= 24 ou sur 64 bit (8 octets) si 25<=n<=53 Comparé au domaine Decimal défini également par intention : decimal[ (p[ ,s] )] ensemble des numériques ayant une précision et une échelle fixes. Où p représente la précision et s représente l'échelle Code :
Tu ne pourras jamais représenter, par exemple, le nombre 1.79E+308 en utilisant le type décimal ! Code :
Donc on ne peut pas toujours remplacer le type Float par le type Decimal. Autres remarques : Nous avons tendance à considérer le type Float comme un ensemble purement mathématique, le confondant souvent avec l'ensemble R ( ensemble des nombre réels en mathématique), ce qui est une erreur. L'ensemble R, au sens mathématique du terme, est un espace topologique au sens limite et continuité. Or le type Float, par définition représenté physiquement, en mémoire, en binaire, par des 0 et 1, au plus sur 8 octets, ne pourra jamais représenter un espace topologique intégrant les notions de limite de continuité. Il ne peut donc s'agir, au mieux, que d'un espace ou d'une topologie discrète où les points sont isolés les uns des autres. Ci-dessous quelques résultats, qui sur le plan mathématique pur, peuvent apparaître surprenant voire même déroutant ! Code :
Code :
De même Code :
Code :
|
||||||||||||
|
|
00
|
Copyright © 2000-2012 - www.developpez.com