私は解を思いつきました。与えられた分母と指名子の集合から、与えられた数の最良の近似が見つけられました。この解決策は見つけよりもセットは、N個の要素を有する場合
=被平方根< = 100000
= root_index < = 20
:このセットにより作成することができるすべての数値を含むことができる。例えば
O(N log N)における最良の近似。
このソリューションでは、Xは分母とYノミネータを表します。
- ソートセットからの各数Xの設定
- から番号:使用
バイナリ検索最小YようにY/X> = input_number
コンペアY/X input_numberの現在最良の近似と
私は抵抗することができませんでしたし、私はそれを実装:
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
struct Number {
// number value
double value;
// number representation
int root_index;
int radicand;
Number(){}
Number(double value, int root_index, int radicand)
: value(value), root_index(root_index), radicand(radicand) {}
bool operator < (const Number& rhs) const {
// in case of equal numbers, i want smaller radicand first
if (fabs(value - rhs.value) < 1e-12) return radicand < rhs.radicand;
return value < rhs.value;
}
void print() const {
if (value - (int)value < 1e-12) printf("%.0f", value);
else printf("sqrt_%d(%d)",root_index, radicand);
}
};
std::vector<Number> numbers;
double best_result = 1e100;
Number best_numerator;
Number best_denominator;
double input;
void compare_approximpation(const Number& numerator, const Number& denominator) {
double value = numerator.value/denominator.value;
if (fabs(value - input) < fabs(best_result - input)) {
best_result = value;
best_numerator = numerator;
best_denominator = denominator;
}
}
int main() {
const int NUMBER_LIMIT = 100000;
const int ROOT_LIMIT = 20;
// only numbers created by this loops will be used
// as numerator and denominator
for(int i=1; i<=ROOT_LIMIT; i++) {
for(int j=1; j<=NUMBER_LIMIT; j++) {
double value = pow(j, 1.0 /i);
numbers.push_back(Number(value, i, j));
}
}
sort(numbers.begin(), numbers.end());
scanf("%lf",&input);
int numerator_index = 0;
for(int denominator_index=0; denominator_index<numbers.size(); denominator_index++) {
// you were interested only in integral denominators
if (numbers[denominator_index].root_index == 1) {
// i use simple sweeping technique instead of binary search (its faster)
while(numerator_index < numbers.size() && numbers[numerator_index].root_index &&
numbers[numerator_index].value/numbers[denominator_index].value <= input) {
numerator_index++;
}
// comparing approximations
compare_approximpation(numbers[numerator_index], numbers[denominator_index]);
if (numerator_index > 0) {
compare_approximpation(numbers[numerator_index - 1], numbers[denominator_index]);
}
}
}
printf("Best approximation %.12lf = ", best_numerator.value/best_denominator.value);
best_numerator.print();
printf("/");
best_denominator.print();
printf("\n");
}
あなたは、少なくともいくつかのCを配置する必要があります可能な出力の制約。あなたが興味を持っているのは整数のsqrtsだけですか? –
"唯一の条件"は、 "sqrt(2)/ 5"を望んでいるようではありません。大規模なkでは有理なR + sqrt(2)/ 10^kが必要です。 – DSM
興味のある分子や分母の平方根にすぎない場合は、アルゴリズムに入力する前に入力を平方化することができます。しかし、もちろん、これは15度の正弦のような単純な数値によって打ち消されます。これは(sqrt(3.0)-1.0)/(2.0 * sqrt(2.0))です。 – thb