C++Guns – RoboBlog

04.07.2019

C++ Guns: Fingerübung: can convert double to int?

Filed under: Allgemein — Tags: — Thomas @ 09:07

Wir bekommen öfter mal große integer Zahlen als double gespeichert in den Daten. Beim konvertieren nach Text (andere story) mit 6 signifikanten Ziffern und wissenschaftlicher Darstellung fallen Ziffern weg. Obwohl die wissenschaftliche Darstellung mit einem Exponent bei ganzen Zahlen nicht nötig wäre.

Fingerübung: Schreibe eine Funktion die true zurück gibt, wenn die übergebene double Zahl in ein 32bit signed integer, ohne Verluste, passt.

Da es UB ist, eine zu große double Zahl einem int zuzuweisen (mit constexpr überprüft), ist die Aufgabe nicht ganz so trivial.

constexpr int xxx = std::numeric_limits<int>::max()+1.0; // error: overflow in constant expression

Noch dazu kann ein Integer mehr negative Zahlen als positive Speichern (Die Null zähl mit). Und es gibt natürlich noch Inf und Nan.
Nach drei Versuchen sieht der Code nun wie folgt aus. constexpr Test inklusive.

#include <limits>
#include <cmath>

constexpr inline bool canConvertToInt(double d) {
  if(std::isnan(d) or std::isinf(d)) return false;
  if(d > 0) {
    return d <= std::numeric_limits<int>::max() and d-int(d)==0;
  } else {
    return d >= std::numeric_limits<int>::min() and d-int(d)==0;
  }
}

  static_assert(canConvertToInt(std::numeric_limits<int>::max()-1));
  static_assert(not canConvertToInt(std::numeric_limits<int>::max()-1 + 0.5));
  static_assert(canConvertToInt(std::numeric_limits<int>::max()));
  static_assert(not canConvertToInt(std::numeric_limits<int>::max()+0.5));

  static_assert(canConvertToInt(std::numeric_limits<int>::min()+1));
  static_assert(not canConvertToInt(std::numeric_limits<int>::min()+1-0.5));
  static_assert(canConvertToInt(std::numeric_limits<int>::min()));
  static_assert(not canConvertToInt(std::numeric_limits<int>::min()-0.5));

  static_assert(not canConvertToInt(std::numeric_limits<double>::infinity()));
  static_assert(not canConvertToInt(std::numeric_limits<double>::quiet_NaN()));
  static_assert(not canConvertToInt(std::numeric_limits<double>::signaling_NaN()));
  static_assert(not canConvertToInt(std::numeric_limits<double>::denorm_min()));

Der Praxistest kann beginnen.

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress