// This is in the public domain
using System;
using System.Numerics;
using static System.Console;
public static class Program
{
private static readonly string Rod = new string('-', 64);
public static void Main()
{
Test(Square(Math.PI), x => ToRational(x), n => (double)n);
Test(Square((decimal)Math.PI), x => ToRational(x), n => (decimal)n);
}
private static double Square(double x) => x * x;
private static decimal Square(decimal x) => x * x;
private static void Test<T>(T value, Func<T, ValueTuple<BigInteger, BigInteger>> toRational, Func<BigInteger, T> toT)
{
WriteLine(Rod);
WriteLine($"value = {value}");
var rational = toRational(value);
BigInteger num = rational.Item1, den = rational.Item2;
WriteLine($"rational = {num}/{den}");
WriteLine($"rational - value = {(dynamic)toT(num) / toT(den) - value}");
}
private static (BigInteger num, BigInteger den) ToRational(double value)
{
var gcd = GCD(value, 1);
return ((BigInteger)(value / gcd), (BigInteger)(1 / gcd));
}
private static (BigInteger num, BigInteger den) ToRational(decimal value)
{
var gcd = GCD(value, 1);
return ((BigInteger)(value / gcd), (BigInteger)(1 / gcd));
}
private static double GCD(double m, double n)
{
while (n != 0)
{
var rem = m % n;
m = n;
n = rem;
}
return m;
}
private static decimal GCD(decimal m, decimal n)
{
while (n != 0)
{
var rem = m % n;
m = n;
n = rem;
}
return m;
}
}
Ly8gVGhpcyBpcyBpbiB0aGUgcHVibGljIGRvbWFpbgp1c2luZyBTeXN0ZW07CnVzaW5nIFN5c3RlbS5OdW1lcmljczsKdXNpbmcgc3RhdGljIFN5c3RlbS5Db25zb2xlOwoKcHVibGljIHN0YXRpYyBjbGFzcyBQcm9ncmFtCnsKCXByaXZhdGUgc3RhdGljIHJlYWRvbmx5IHN0cmluZyBSb2QgPSBuZXcgc3RyaW5nKCctJywgNjQpOwoJCglwdWJsaWMgc3RhdGljIHZvaWQgTWFpbigpCgl7CgkJVGVzdChTcXVhcmUoTWF0aC5QSSksIHggPT4gVG9SYXRpb25hbCh4KSwgbiA9PiAoZG91YmxlKW4pOwoJCVRlc3QoU3F1YXJlKChkZWNpbWFsKU1hdGguUEkpLCB4ID0+IFRvUmF0aW9uYWwoeCksIG4gPT4gKGRlY2ltYWwpbik7Cgl9CgkKCXByaXZhdGUgc3RhdGljIGRvdWJsZSBTcXVhcmUoZG91YmxlIHgpID0+IHggKiB4OwoJCglwcml2YXRlIHN0YXRpYyBkZWNpbWFsIFNxdWFyZShkZWNpbWFsIHgpID0+IHggKiB4OwoJCglwcml2YXRlIHN0YXRpYyB2b2lkIFRlc3Q8VD4oVCB2YWx1ZSwgRnVuYzxULCBWYWx1ZVR1cGxlPEJpZ0ludGVnZXIsIEJpZ0ludGVnZXI+PiB0b1JhdGlvbmFsLCBGdW5jPEJpZ0ludGVnZXIsIFQ+IHRvVCkKCXsKCQlXcml0ZUxpbmUoUm9kKTsKCQlXcml0ZUxpbmUoJCJ2YWx1ZSA9IHt2YWx1ZX0iKTsKCQl2YXIgcmF0aW9uYWwgPSB0b1JhdGlvbmFsKHZhbHVlKTsKCQlCaWdJbnRlZ2VyIG51bSA9IHJhdGlvbmFsLkl0ZW0xLCBkZW4gPSByYXRpb25hbC5JdGVtMjsKCQlXcml0ZUxpbmUoJCJyYXRpb25hbCA9IHtudW19L3tkZW59Iik7CgkJV3JpdGVMaW5lKCQicmF0aW9uYWwgLSB2YWx1ZSA9IHsoZHluYW1pYyl0b1QobnVtKSAvIHRvVChkZW4pIC0gdmFsdWV9Iik7Cgl9CgkKCXByaXZhdGUgc3RhdGljIChCaWdJbnRlZ2VyIG51bSwgQmlnSW50ZWdlciBkZW4pIFRvUmF0aW9uYWwoZG91YmxlIHZhbHVlKQoJewoJCXZhciBnY2QgPSBHQ0QodmFsdWUsIDEpOwoJCXJldHVybiAoKEJpZ0ludGVnZXIpKHZhbHVlIC8gZ2NkKSwgKEJpZ0ludGVnZXIpKDEgLyBnY2QpKTsKCX0KCQoJcHJpdmF0ZSBzdGF0aWMgKEJpZ0ludGVnZXIgbnVtLCBCaWdJbnRlZ2VyIGRlbikgVG9SYXRpb25hbChkZWNpbWFsIHZhbHVlKQoJewoJCXZhciBnY2QgPSBHQ0QodmFsdWUsIDEpOwoJCXJldHVybiAoKEJpZ0ludGVnZXIpKHZhbHVlIC8gZ2NkKSwgKEJpZ0ludGVnZXIpKDEgLyBnY2QpKTsKCX0KCQoJcHJpdmF0ZSBzdGF0aWMgZG91YmxlIEdDRChkb3VibGUgbSwgZG91YmxlIG4pCgl7CgkJd2hpbGUgKG4gIT0gMCkKCQl7CgkJCXZhciByZW0gPSBtICUgbjsKCQkJbSA9IG47CgkJCW4gPSByZW07CgkJfQoJCXJldHVybiBtOwoJfQoJCglwcml2YXRlIHN0YXRpYyBkZWNpbWFsIEdDRChkZWNpbWFsIG0sIGRlY2ltYWwgbikKCXsKCQl3aGlsZSAobiAhPSAwKQoJCXsKCQkJdmFyIHJlbSA9IG0gJSBuOwoJCQltID0gbjsKCQkJbiA9IHJlbTsKCQl9CgkJcmV0dXJuIG07Cgl9Cn0=