patterncppMinor
Storing angles with overflow errors
Viewed 0 times
withoverflowangleserrorsstoring
Problem
Rather than checking if my angle is in the range of 0 to 2pi every time it gets set, I got the idea to store it as an unsigned short with 0xFFFF being +2pi, thus the standard overflow behavior for unsigned numbers should keep it bound to the desired range.
Is it a good idea to do it this way, or is there something I'm missing?
```
#ifndef ANGLE_H
#define ANGLE_H
#include
class Angle
{
//static constexpr long double _PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348;
static constexpr long double _TWO_PI = 6.2831853071795864769252867665590057683943387987502116419498891846156328125724179972560696;
static inline __attribute((always_inline)) __attribute((pure))
uint16_t uint16_from_double(const double a) { return (a * 0x00010000) / _TWO_PI; }
uint16_t _theta;
Angle(uint16_t theta) :
_theta(theta)
{
}
public:
Angle(double t = 0) :
_theta(uint16_from_double(t));
{
}
inline operator double() const
{
return radians();
}
inline double radians() const { return ((double) _theta) / 0x00010000) * _TWO_PI; }
inline double degrees() const { return ((double) _theta) / 0x00010000) * 360; }
//everything is less than and greater than everything else, because it's a circle
//so return if subtracting will get us there faster than adding...
inline bool operator= 0x00008000;
}
inline bool operator 0x00008000;
}
inline bool operator>(const Angle & it) const
{
return _theta 0x00008000 : (_theta - it._theta) =(const Angle & it) const
{
return _theta = 0x00008000 : (_theta - it._theta) < 0x00008000;
}
inline Angle minDelta(const Angle & it) const
{
uint16_t i = _theta < it._theta? it._theta - _theta : _theta - it._theta;
return Angle(i < 0x00007FFF? i : 0x00010000 - i);
}
inline const Angle & operator=(double a)
{
_theta = uint16_from_double(a);
re
Is it a good idea to do it this way, or is there something I'm missing?
```
#ifndef ANGLE_H
#define ANGLE_H
#include
class Angle
{
//static constexpr long double _PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348;
static constexpr long double _TWO_PI = 6.2831853071795864769252867665590057683943387987502116419498891846156328125724179972560696;
static inline __attribute((always_inline)) __attribute((pure))
uint16_t uint16_from_double(const double a) { return (a * 0x00010000) / _TWO_PI; }
uint16_t _theta;
Angle(uint16_t theta) :
_theta(theta)
{
}
public:
Angle(double t = 0) :
_theta(uint16_from_double(t));
{
}
inline operator double() const
{
return radians();
}
inline double radians() const { return ((double) _theta) / 0x00010000) * _TWO_PI; }
inline double degrees() const { return ((double) _theta) / 0x00010000) * 360; }
//everything is less than and greater than everything else, because it's a circle
//so return if subtracting will get us there faster than adding...
inline bool operator= 0x00008000;
}
inline bool operator 0x00008000;
}
inline bool operator>(const Angle & it) const
{
return _theta 0x00008000 : (_theta - it._theta) =(const Angle & it) const
{
return _theta = 0x00008000 : (_theta - it._theta) < 0x00008000;
}
inline Angle minDelta(const Angle & it) const
{
uint16_t i = _theta < it._theta? it._theta - _theta : _theta - it._theta;
return Angle(i < 0x00007FFF? i : 0x00010000 - i);
}
inline const Angle & operator=(double a)
{
_theta = uint16_from_double(a);
re
Solution
I find it amusing that you have written
You could use one of these suggestions for the value of π. In any case, you should never use an identifier with a leading underscore — names with one underscore are reserved for standard libraries, two underscores for the compiler.
_TWO_PI out to 89 digits of precision. The ratio of the circumference of the observable universe relative to the size of a hydrogen atom is just 40 digits, which means that you couldn't possibly need any more precision than that for any physical calculation. In any case, you're quantizing it to a uint16_t, which gives you less precision than a float, so even long double is overkill.You could use one of these suggestions for the value of π. In any case, you should never use an identifier with a leading underscore — names with one underscore are reserved for standard libraries, two underscores for the compiler.
Context
StackExchange Code Review Q#148354, answer score: 3
Revisions (0)
No revisions yet.