J'ai ce petit bout de code

double s = -2.6114289999999998;
double s7 = Math.Round(s, 7);
double s5 = Math.Round(s, 5);
double s6 = Math.Round(s, 6);

Avec Platform = Any CPU, j'obtiens

s7: -2.611429   
s5: -2.61143    
s6: -2.611429   

Avec Platform = x64, j'obtiens

s7: -2.6114289999999998 
s5: -2.61143    
s6: -2.6114289999999998

Pourquoi? (Sortie copiée depuis la fenêtre Locals de VS)


L'ensemble du code est:

    private void btnAlign_Click(object sender, EventArgs e)
    {
        double s = -2.6114289999999998;
        double s7 = Math.Round(s, 7);
        double s5 = Math.Round(s, 5);
        double s6 = Math.Round(s, 6);
    }
16
beyond 15 nov. 2017 à 11:37

4 réponses

Meilleure réponse

La valeur -2.611429 ne peut pas être représentée en virgule flottante 64 bits. Lors de la compilation en mode 32 bits, la valeur utilisera à la place 80 bits (précision étendue).

4
l33t 15 nov. 2017 à 09:00

Sur x64, le FPU SSE2 est utilisé et sur x86, le FPU x87 est utilisé.

Il est possible (bien que non conseillé) de modifier la précision x87 pour qu'elle soit la même que la précision SSE2 (c'est-à-dire, utilisez une précision inférieure).

Vous pouvez le faire via _controlfp() API.

Le programme suivant démontre. Exécutez ce programme en mode x86 et vous verrez comment l'utilisation de _controlfp(0x00030000, 0x00020000) fait que la sortie change pour être similaire (mais pas tout à fait la même!) À la version x64:

using System;
using System.Runtime.InteropServices;

namespace ConsoleApp3
{
    class Program
    {
        static void Main()
        {
            double s = -2.6114289999999998;

            Console.WriteLine(Math.Round(s, 7).ToString("R")); // -2.611429

            if (!Environment.Is64BitProcess)
                _controlfp(0x00030000, 0x00020000);

            Console.WriteLine(Math.Round(s, 7).ToString("R")); // -2.61142897605896
        }

        [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint _controlfp(uint newcw, uint mask);
    }
}

Cependant, vous ne devez pas jouer avec le FPU de cette manière (et si vous le faites, vous devez revenir au paramètre précédent dès que possible).

4
Matthew Watson 15 nov. 2017 à 09:40

Réponse ici: https://stackoverflow.com/a/19978623/4891523

Le code managé x64 utilisera SSE pour le calcul double / float au lieu de x87 FPU lors de l'utilisation de code managé x86.

1
Liam 15 nov. 2017 à 08:47

Selon la spécification du langage CSharp 3.0, ce qui suit peut être le cas:

Voir le chapitre 4.1.6 à la spécification pour plus d'informations

Les opérations à virgule flottante peuvent être effectuées avec une précision plus élevée que le type de résultat de l'opération. Par exemple, certaines architectures matérielles prennent en charge un type à virgule flottante "étendu" ou "long double" avec une plage et une précision supérieures à celles du type double, et exécutent implicitement toutes les opérations en virgule flottante en utilisant ce type de précision supérieure. Ce n'est qu'à un coût excessif en termes de performances que de telles architectures matérielles peuvent être conçues pour effectuer des opérations en virgule flottante avec moins de précision, et plutôt que d'exiger une implémentation pour perdre à la fois les performances et la précision, C # permet d'utiliser un type de précision plus élevée pour toutes les opérations en virgule flottante . En plus de fournir des résultats plus précis, cela a rarement des effets mesurables. Cependant, dans les expressions de la forme x * y / z, où la multiplication produit un résultat qui est en dehors de la plage double, mais la division suivante ramène le résultat temporaire dans la plage double, le fait que l'expression est évaluée dans une plage supérieure Le format de plage peut provoquer la production d'un résultat fini au lieu d'une infinité.

En bref: la spécification C # indique en fait que les architectures matérielles peuvent avoir un impact sur les types à virgule flottante (Double, Float).

La spécification du langage comme .doc peut être trouvée ici.

2
LOLWTFasdasd asdad 15 nov. 2017 à 09:01
47302758