Question

J'ai une méthode qui traite des coordonnées géographiques dans .NET, et j'ai un struct qui stocke une paire de coordonnées de telle sorte que si 256 est passé dans l'un des coordonnées, il devient 0. Cependant, dans un cas particulier une valeur d'environ 255.99999998 est calculée, et donc stocké dans le struct. Quand il est imprimé en ToString (), il devient 256, qui ne devrait pas se produire - 256 devrait être 0. Je ne me dérangerait pas si elle imprimé 255,9999998 mais le fait qu'il imprime 256 lorsque le débogueur montre 255.99999998 est un problème. il ayant à la fois magasin et affichage 0 serait encore mieux.

Plus précisément il y a un problème avec la comparaison. 255.99999998 est suffisamment proche de 256 telle qu'elle devrait l'égaler. Que dois-je faire lorsque l'on compare double? utiliser une sorte de valeur epsilon?


EDIT:. Plus précisément, mon problème est que je prends une valeur, effectuer des calculs, puis effectuer les calculs opposés sur ce nombre, et je dois retourner la valeur initiale exactement

Était-ce utile?

La solution

Vous pouvez utiliser l'approche epsilon, mais l'epsilon est généralement un fudge pour contourner le fait que l'arithmétique en virgule flottante est lossy.

Vous pourriez envisager d'éviter binaire points flottants et tout à fait utiliser une belle classe rationnelle.

Le calcul a été ci-dessus probablement destiné à être 256 si vous faisiez l'arithmétique sans perte que vous obtiendriez avec un type rationnel.

types rationnelles peuvent aller sous le nom de Ratio ou classe Fraction, et sont assez simples à écrire

Voici une exemple . Voici autre


Modifier ....

Pour comprendre votre problème considérer que lorsque la valeur décimale 0,01 est convertie en une représentation binaire, il ne peut pas être stocké dans la mémoire exactement finie. La représentation Hexidecimal pour cette valeur est 0.028F5C28F5C où le « 28F5C » répète à l'infini. Ainsi, même avant de faire des calculs, vous perdez juste précision en stockant 0,01 au format binaire.

Classes rationnelles et décimales sont utilisées pour résoudre ce problème, mais avec un coût de performance. types rationnels éviter ce problème en stockant un numérateur et un dénominateur pour représenter votre valeur. Type décimal utilisé binaire codé décimal , qui peut être lossy dans la division, mais peut stocker des valeurs décimales communes exactement.

Pour votre but, je suggère encore un type rationnel.

Autres conseils

Cela ressemble à un problème avec la façon dont le nombre est imprimé, pas comment il est stocké. Un double a environ 15 chiffres significatifs, il peut donc dire 255,99999998 de 256 avec une précision de rechange.

Vous pouvez choisir les chaînes de format qui devrait vous permettre d'afficher autant du nombre que vous le souhaitez.

La façon habituelle de comparer double pour l'égalité est de les soustraire et si la valeur absolue est inférieure à une epsilon prédéfinie, peut-être 0,000001.

Vous devez vous décider d'un seuil en dessous duquel deux valeurs sont égales. Cela revient à utiliser ce qu'on appelle nombres à virgule fixe (par opposition à virgule flottante). Ensuite, vous devez effectuer le tour manuellement.

J'irait avec un certain type non signé avec la taille connue (par exemple. Uint32 ou uint64 si elles sont disponibles, je ne sais pas .NET) et le traiter comme un mod type de numéro de point fixe 256.

Par exemple.

typedef uint32 fixed;

inline fixed to_fixed(double d)
{
    return (fixed)(fmod(d, 256.) * (double)(1 << 24))
}

inline double to_double(fixed f)
{
    return (double)f / (double)(1 << 24);
}

ou quelque chose de plus élaboré pour répondre à une convention d'arrondissement (au plus proche, à la baisse, à la hausse, à étrange, à même). Les plus fortes 8 bits de maintien fixe de la partie entière, les 24 bits inférieurs occupent la partie fractionnaire. La précision absolue est 2 ^ {- 24}

.

Notez que l'ajout et la soustraction de ces nombres enveloppe naturellement autour de 256. Pour la multiplication, vous devriez vous méfier.

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