2016-07-17 2 views
-2

J'essaie de faire une fonction d'opérateur de modèle pour soustraire un scalaire d'un vecteur et retourner le résultat dans un vecteur. La fonction ci-dessous est ce que je suis en mesure de venir avec:L'opérateur de modèle C++ donne un mauvais résultat en soustrayant un scalaire d'un vecteur

// vector - scalar 
template<typename T1, typename T2> 
auto operator - (const Vector<T1> & lhs, const T2 & scalar)-> Vector<std::common_type_t<T1,T2>> 
{ 
    using T3 = std::common_type_t<T1, T2>; 
    Vector<T3> result; 
    result.base.reserve(lhs.base.size()); 
    std::transform(lhs.base.begin(), lhs.base.end(), std::back_inserter(result.base), 
      [&scalar](const T3 & element) { return element - scalar; }); 
    return result; 
} 

Cependant, le résultat est pas correct, en essayant de soustraire un scalaire (float) à partir d'un vecteur (int). Je suspecte le problème parce que les opérandes subissent les conversions arithmétiques habituelles, qui incluent promotions intégrales.

DEMO

+1

"n'est pas correct", et "mauvais résultat", ne sont pas une description de problème utile. Un test simple produit le résultat attendu, en utilisant 'std :: vector ' et un scalaire 'float' donne un résultat' std :: vector ' avec les bonnes valeurs. Ne peut pas reproduire. Définir "mauvais résultat". –

+0

@Sam Varshavchik, pas sûr de ce que vous entendez par "Impossible de reproduire" - le but de la démo était de reproduire le problème. Quoi qu'il en soit, l'exemple montre: v - s = (1, 2, 3) - 2.1 = (-1.1, -0.0999999, 0.9), ce qui est faux. Le résultat correct est le vecteur: [-1.1f, -0.1f, 0.9f]. Ce qui me laisse perplexe est que le deuxième élément donne -0.0999999 et les autres éléments sont corrects. – bobster

+1

Non, ces résultats sont corrects. Ce qui vous manque est le fait que [les nombres à virgule flottante ne sont pas exacts, et n'ont jamais été exacts en C++, ou dans la plupart des langages de programmation modernes] (http://stackoverflow.com/questions/588004/is-floating-point-math -cassé). –

Répondre

1

Cela n'a rien à voir avec les modèles, mais avec le fait que les nombres à virgule flottante ne sont pas exactes.

Cela produit le même « mauvais résultat » vous a spécifiquement cité dans les commentaires:

float subtract(float a, float b) 
{ 
    return a-b; 
} 

int main() 
{ 
    std::cout << subtract(2, 2.1) << std::endl; 

    return 0; 
} 

Essayez de compiler vous-même, et voir ce que le résultat est.

C'est aussi -0,0999999.

Bienvenue dans le monde merveilleux des mathématiques en virgule flottante.

Si vous avez besoin d'une précision mathématique précise, il existe des bibliothèques spécialisées qui l'implémentent.

+0

Vous avez raison, cela n'a rien à voir avec les templates, juste que l'arithmétique en virgule flottante C/C++ n'est pas exacte. J'ai essayé d'utiliser la méthode "AlmostEqual2sComplement" de Bruce Dawson (https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/) dans mon opérateur égal. Encore besoin d'un peu de peaufinage. – bobster