[ot][spam][crazy] Inhibition Efforts: High-Precision
It feels like one of my inhibitions is around making things that are more accurate than useful. So, maybe a good little bit of code for me could be measuring a laptop or cell phones average battery level to unlimited precision. The definition of 'average' may remain vague, unsure. Maybe I can use a rational number library.
BIGRAT bigrat means computer code for rational numbers of arbitrary precision ("big" "rat"ional) https://gmplib.org/ The GNU Multiple Precision Arithmetic Library GMP is a free library for arbitrary precision arithmetic, operating on signed integers, rational numbers, and floating-point numbers. There is no practical limit to the precision except the ones implied by the available memory in the machine GMP runs on. GMP has a rich set of functions, and the functions have a regular interface. GMP is used in pretty much everything!
GMP function categories High-level signed integer arithmetic functions (mpz). There are about 150 arithmetic and logic functions in this category. High-level rational arithmetic functions (mpq). This category consists of about 35 functions, but all mpz functions can be used too, by applying them to the numerator and denominator separately.
those were the first 2 categories, these are the remaining 3. i added because the last one says there are some functions that are optimized for extra speed. - High-level floating-point arithmetic functions (mpf). This is the GMP function category to use if the C type `double' doesn't give enough precision for an application. There are about 70 functions in this category. New projects should strongly consider using the much more complete GMP extension library mpfr instead of mpf. - C++ class based interface to all of the above. (The C functions and types can of course be used directly from C++ too.) - Low-level positive-integer, hard-to-use, very low overhead functions are found in the mpn category. No memory management is performed; the caller must ensure enough space is available for the results. The set of functions is not always regular, nor is the calling interface. These functions accept input arguments in the form of pairs consisting of a pointer to the least significant word, and an integral size telling how many limbs (= words) there are in that argument. The functions in the other categories call mpn for almost all their calculations. Of these functions about 60 are public.
maybe a great starting challenge would be to just calculate a very precise number, at all! ther'es probably even an mpq (bigrat) example for that!
the gmp c functions have a lot of boilerplate characters i think there'd be more return using the c++ ones. less boilerplate to process with classes.
here's their example: #include <gmpxx.h> // g++ mycxxprog.cc -lgmpxx -lgmp int main (void) { mpz_class a, b, c; a = 1234; b = "-5678"; c = a+b; cout << "sum is " << c << "\n"; cout << "absolute value is " << abs(c) << "\n"; return 0; }
I made a bigrat one! #include <gmpxx.h> #include <iostream> int main() { mpq_class a, b; a = 1; b = 3; std::cout << "1/3=" << (a/b) << std::endl; } // outputs 1/3=1/3
basically, whatever funny kind of interpolation or sampling error I have, with logging forever the precision of an average will grow. it's better if the interpolation represents what is real. but it works to do anything at all, such as what is easiest to implement. it could make sense to have some way to reprocess the data in a different manner
yay, battery averages! I thought about just averaging the values, and I was like "why wasn't i considering this", but when thinking about it I'd rather do a linear or stepwise interpolation, so that times when the values can be polled faster or slower don't impact it as much. This seems to make sense for battery charge, which is not expected to spike. I'm not sure how it works out for current, if there are spikes. Seems like either way it's a fudge, and you'd want to run the process at realtime priority or something. I dunno.
yay, battery averages! I'm totally gonna conquer those ... high precision fractions with large data storage associated with them.
i began opening a new tmux window to do this, not sure where to find the work i just did. i experienced complaint, and felt i barely managed to find it. i feel lucky it was one window previous to the last one.
// g++ -lgmpxx -lgmp #include <gmpxx.h> #include <string> #include <iostream> #include <ctime> #include <cerrno> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> mpq_class now() { struct timespec t; if (clock_gettime(CLOCK_MONOTONIC, &t)) { throw std::runtime_error(std::strerror(errno)); } return t.tv_sec + mpq_class(t.tv_nsec) / 1000000000; } class Measurer { public: Measurer(char const * input_filename) : current_time(0), fd(open(input_filename, O_RDONLY)) { } ~Measurer() { close(fd); } void measure() { last_time = current_time; last_value = current_value; lseek(fd, 0, SEEK_SET); int len = read(fd, buf, sizeof(buf)); buf[len] = 0; if (buf[len-1] == '\n') { buf[len-1] = 0; } current_time = now(); current_value = buf; if (last_time != 0) { time_change = current_time - last_time; accumulated_time += time_change * 2; accumulated_timevalues += time_change * (last_value + current_value); } } mpq_class value() { return accumulated_timevalues / accumulated_time; } mpq_class & time() { return last_time; } private: int fd; mpq_class last_time; mpq_class last_value; mpq_class current_time; mpq_class current_value; mpq_class time_change; mpq_class accumulated_time; mpq_class accumulated_timevalues; char buf[1024]; }; int main(int argc, char **argv) { if (argc != 2) { std::cout << "Usage: " << argv[0] << " filepath-containing-a-changing-number" << std::endl; return -1; } Measurer measurer(argv[1]); mpq_class start_time = now(); while ("reading numbers from filepath") { measurer.measure(); if (start_time + 1 <= measurer.time()) { std::cout << "Average: " << measurer.value().get_d() << std::endl; start_time += 1; } } }
it's cool i did it and i learned gmp a little bit. it looks like outputting an arbitrary precision decimal would be done manually by converting from a rational to an arbitrary precision float of appropriate precision. hard to repeat. worth repeating a lot i suppose.
also missing: - don't perform calculation when value doesn't change [easy] - consider performance hit of large numbers
participants (1)
-
Undiscussed Horrific Abuse, One Victim of Many