/      日本語

div10(), div100(), div1000()

Calculate quotient and remainder when divided by 10, 100, or 1000
Calculates the quotient and remainder when divided by 10, 100, or 1000.
struct div_result_i32 {
		int32_t quo; // quotient
		int16_t rem; // remainder
		uint8_t b_neg;  // true if negative
		uint8_t digits_rem; // digits of remainder
};

div_result_i32 div10(int32_t val);
div_result_i32 div100(int32_t val);
div_result_i32 div1000(int32_t val);

In some cases, sensor values multiplied by 100 are passed as uint16_t type, but on microcontrollers without division circuits, calculation processing takes considerable time. Therefore, calculations are performed using approximate calculations and corrections with addition, subtraction, multiplication, and bit shifts.

Pass the value to be calculated in val, the variable to store the remainder in rem, and the variable to store the sign in neg.

The return value is the quotient (always positive), rem contains the remainder (always positive), and neg stores true if negative.

Due to algorithm constraints (digit overflow), the calculable value range is limited for div100() and div1000(). div100() supports values from -99999 to 99999, and div1000() supports values from -999999 to 999999.

Example usage

auto d1 = div100(sns_val.u16temp_object);
auto d2 = div100(sns_val.u16temp_object);

Serial
	<< crlf << format("..Object  = %c%2d.%02d"
									, d1.b_neg ? '-' : '+', d1.quo, d1.rem)
	        << format("  Ambient = %c%2d.%02d"
									, d2.b_neg ? '-' : '+', d2.quo, d2.rem);

Calculation speed

About one-tenth of the time.

Output of results

// Conversion options
struct DIVFMT {
  static const int STD = 0; // displays with minimal digits (no padding, no positive sign)
  static const int PAD_ZERO = 1; // set padding character as '0' instead of ' '.
  static const int SIGN_PLUS = 2; // put '+' sign if value is positive or 0.
  static const int PAD_ZERO_SIGN_PLUS = 3; // PAD_ZERO & SIGN_PLUS
  static const int SIGN_SPACE = 4; // put ' ' sign if value is positive or 0.
  static const int PAD_ZERO_SIGN_SPACE = 5; // PAD_ZERO & SIGN_SPACE
};

// Class to store string conversion results
class _div_chars {
  ...
  const char* begin() const {...}
  const char* end() const {...}
  const char* c_str() const { return begin(); }
  operator const char*() const { return begin(); }
};

// format() method
_div_chars div_result_i32::format(
    int dig_quo = 0, uint32_t opt = DIVFMT::STD) const;

// Implementation of interface to Serial
template <class D> class stream {
...
		inline D& operator << (const mwx::_div_chars&& divc);
		inline D& operator << (const mwx::div_result_i32&&);
		inline D& operator << (const mwx::div_result_i32&);
};

The div_result_i32 class that stores the division result has a format() method to obtain a _div_chars class object. The _div_chars class object contains a string buffer and provides methods to access the string buffer as const char*. Also, the << operator for the Serial object is implemented.

The first parameter dig_quo of the format() method specifies the number of output digits (excluding the sign). If the output digits are insufficient (below), it is filled with spaces or 0. The second parameter opt specifies the format.

opt parameterDescription
DIVFMT::STDStandard output, fills insufficient digits with spaces, and adds - only for negative values.
DIVFMT::PAD_ZEROFills insufficient digits with 0.
DIVFMT::SIGN_PLUSAdds + sign for positive values as well.
DIVFMT::PAD_ZERO_SIGN_PLUSFills insufficient digits with 0 and adds + sign for positive values.
DIVFMT::SIGN_SPACEAdds a space sign instead of + for positive values.
DIVFMT::PAD_ZERO_SIGN_SPACEFills insufficient digits with 0 and adds a space sign instead of + for positive values.

Example

//// Direct output from div_result_i32 object
Serial << div100(-1234) << crlf;
// Result: -12.34

//// Output with 3 digits
Serial << div100(3456).format(3, DIVFMT::PAD_ZERO_SIGN_PLUE) << crlf;
// Result: +034.56

//// Use c_str() to get const char*
char str1[128];
auto x = div100(-5678);
mwx_snprintf(str1, 16, "VAL=%s", x.format.c_str()); // const char*
Serial << str1;
// Result: VAL=-56.78

Background

In TWELITE BLUE/RED, division is a costly operation, so a division algorithm with limited purposes was added.

Within the library, some sensor values such as temperature and humidity are represented using values multiplied by 100 (e.g., 25.12℃ as 2512), so a simple procedure to obtain the quotient and remainder when divided by 100 was defined.

dev_result_i32::format() is provided to avoid complexity when formatting output.