Сравнение чисел с плавающей запятой с ограниченной точностью

Нужно сравнить следующие пары чисел с точностью до 4-х значащих цифр.

  1. 1134 и 1132
  2. 9933 и 9932
  3. 11344 и 11342
  4. 99343 и 99342.

Соответственно, в первых двух случаях числа получаются неравными, а в последних - равными. Пробовал ввести заранее eps=0.001, и сравнивать его с относительными погрешностями, но не все тесты проходят. Также выяснил, что первая значащая цифра влияет на порядок числа. Как проделать это решение чисто математически, чтобы потом уже написать на любом языке?


Ответы (2 шт):

Автор решения: n1tr0xs

Я бы делал так:

  1. Ищем максимальное 10^n, такое, что оно меньше данного числа.
  2. Делим найденное число на 1000.
  3. Сравниваем результаты деления чисел на свои 10^n.

Примеры на ЯП

C++

#include <iostream>
#include <cmath>

using namespace std;

int get_d(int n){
    return pow(10, int(log10(n)))/1000;
}

bool is_equal(int n1, int n2){
    return n1/get_d(n1) == n2/get_d(n2);
}

int main(){
    int n1, n2;

    n1 = 99344;
    n2 = 99346;

    cout << is_equal(n1, n2);

    return 0;
}
→ Ссылка
Автор решения: CrazyElf

На питоне вообще в строковом виде проще решить:

def compare_n(a, b, n):
    return str(a)[:n] == str(b)[:n] 

assert(not compare_n(1134, 1132, 4))
assert(not compare_n(9933, 9932, 4))
assert(compare_n(11344, 11342, 4))
assert(compare_n(99343, 99342, 4))

Но можно и математически:

import math

def cut_n(x, n):
    ix = int(math.log10(x)) + 1
    return x // math.pow(10, ix - n if n < ix else 0)

def compare_n(a, b, n):
    return cut_n(a, n) == cut_n(b, n)

assert(not compare_n(1134, 1132, 4))
assert(not compare_n(9933, 9932, 4))
assert(compare_n(11344, 11342, 4))
assert(compare_n(99343, 99342, 4))
→ Ссылка