How to resolve the algorithm Minkowski question-mark function step by step in the C++ programming language

Published on 7 June 2024 03:52 AM

How to resolve the algorithm Minkowski question-mark function step by step in the C++ programming language

Table of Contents

Problem Statement

The Minkowski question-mark function converts the continued fraction representation [a0; a1, a2, a3, ...] of a number into a binary decimal representation in which the integer part a0 is unchanged and the a1, a2, ... become alternating runs of binary zeroes and ones of those lengths. The decimal point takes the place of the first zero. Thus, ?(31/7) = 71/16 because 31/7 has the continued fraction representation [4;2,3] giving the binary expansion 4 + 0.01112. Among its interesting properties is that it maps roots of quadratic equations, which have repeating continued fractions, to rational numbers, which have repeating binary digits. The question-mark function is continuous and monotonically increasing, so it has an inverse.

Don't worry about precision error in the last few digits.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Minkowski question-mark function step by step in the C++ programming language

The provided code is implemented in C++ and performs the following tasks:

  1. It defines the Minkowski function and its inverse.
  2. It uses these functions to demonstrate the relationship between them and to evaluate some specific values.

Here's a detailed explanation:

  1. Minkowski Function (minkowski):

    • This function takes a double-precision floating-point number x as input and calculates its Minkowski approximation using a continued fraction expansion.
    • If x is not between 0 and 1, it calls itself recursively to approximate the integer part and the fractional part separately.
    • For values between 0 and 1, it uses a loop to calculate the continued fraction expansion until a certain precision is reached or the maximum number of iterations is exceeded.
    • The result is the Minkowski approximation of x.
  2. Minkowski Inverse Function (minkowski_inverse):

    • This function takes a double-precision floating-point number x as input and calculates its inverse Minkowski approximation using a continued fraction expansion.
    • If x is not between 0 and 1, it calls itself recursively to approximate the integer part and the fractional part separately.
    • For values between 0 and 1, it uses a loop to calculate the continued fraction expansion until a certain precision is reached or the maximum number of iterations is exceeded.
    • The result is the inverse Minkowski approximation of x.
  3. Main Function (main):

    • The main function demonstrates the usage of the minkowski and minkowski_inverse functions. It evaluates and prints four pairs of values:
      • minkowski(0.5 * (1 + sqrt(5))) and 5.0 / 3.0
      • minkowski_inverse(-5.0 / 9.0) and (sqrt(13) - 7) / 6
      • minkowski(minkowski_inverse(0.718281828182818)) and 0.718281828182818
      • minkowski_inverse(minkowski(0.1213141516271819)) and 0.1213141516171819
    • These pairs of values demonstrate the relationship between the Minkowski function and its inverse, and how they can be used to approximate irrational numbers.
  4. Continued Fraction Expansion:

    • Both the minkowski and minkowski_inverse functions use continued fraction expansions to approximate irrational numbers. A continued fraction is a way of representing a real number as a nested series of fractions. This representation can be used to efficiently compute approximations of the number.

In summary, this code defines and demonstrates the use of the Minkowski function and its inverse to approximate irrational numbers using continued fraction expansions. It shows how these functions can be used to evaluate specific values and demonstrates the relationship between the two functions.

Source code in the cpp programming language

#include <cmath>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <vector>

constexpr int32_t MAX_ITERATIONS = 151;

double minkowski(const double& x) {
	if ( x < 0 || x > 1 ) {
		return floor(x) + minkowski(x - floor(x));
	}

	int64_t p = (int64_t) x;
	int64_t q = 1;
	int64_t r = p + 1;
	int64_t s = 1;
	double d = 1.0;
	double y = (double) p;

	while ( true ) {
		d /= 2;
		if ( d == 0.0 ) {
			break;
		}

		int64_t m = p + r;
		if ( m < 0 || p < 0 ) {
			break;
		}

		int64_t n = q + s;
		if ( n < 0 ) {
			break;
		}

		if ( x < (double) m / n ) {
			r = m;
			s = n;
		} else {
			y += d;
			p = m;
			q = n;
		}
	}
	return y + d;
}

double minkowski_inverse(double x) {
	if ( x < 0 || x > 1 ) {
		return floor(x) + minkowski_inverse(x - floor(x));
	}

	if ( x == 0 || x == 1 ) {
		return x;
	}

	std::vector<int32_t> continued_fraction(1, 0);
	int32_t current = 0;
	int32_t count = 1;
	int32_t i = 0;

	while ( true ) {
		x *= 2;
		if ( current == 0 ) {
			if ( x < 1 ) {
				count += 1;
			} else {
				 continued_fraction.emplace_back(0);
				 continued_fraction[i] = count;

				 i += 1;
				 count = 1;
				 current = 1;
				 x -= 1;
			}
		} else {
			 if ( x > 1 ) {
				 count += 1;
				 x -= 1;
			 } else {
				 continued_fraction.emplace_back(0);
				 continued_fraction[i] = count;

				 i += 1;
				 count = 1;
				 current = 0;
			 }
		}

		if ( x == floor(x) ) {
			 continued_fraction[i] = count;
			 break;
		}

		if ( i == MAX_ITERATIONS ) {
			 break;
		}
	}

	double reciprocal = 1.0 / continued_fraction[i];
	for ( int32_t j = i - 1; j >= 0; --j ) {
		 reciprocal = continued_fraction[j] + 1.0 / reciprocal;
	}

	return 1.0 / reciprocal;
}

int main() {
	std::cout << std::setw(20) << std::fixed << std::setprecision(16) << minkowski(0.5 * ( 1 + sqrt(5) ))
			  << std::setw(20) << 5.0 / 3.0 << std::endl;
	std::cout << std::setw(20) << minkowski_inverse(-5.0 / 9.0)
			  << std::setw(20) << ( sqrt(13) - 7 ) / 6  << std::endl;
	std::cout << std::setw(20) << minkowski(minkowski_inverse(0.718281828182818))
			  << std::setw(20) << 0.718281828182818 << std::endl;
	std::cout << std::setw(20) << minkowski_inverse(minkowski(0.1213141516271819))
			  << std::setw(20) << 0.1213141516171819 << std::endl;
}


  

You may also check:How to resolve the algorithm Binary search step by step in the Simula programming language
You may also check:How to resolve the algorithm Strip a set of characters from a string step by step in the COBOL programming language
You may also check:How to resolve the algorithm Damm algorithm step by step in the Action! programming language
You may also check:How to resolve the algorithm Knapsack problem/Bounded step by step in the FreeBASIC programming language
You may also check:How to resolve the algorithm Left factorials step by step in the Tcl programming language