powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Задачка из области математики.
9 сообщений из 9, страница 1 из 1
Задачка из области математики.
    #39419016
mikron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть вещественное число R, которое представлено в переменной типа double (IEEE 754)
Нужно найти наибольшую десятичную мантису, которая удовлетворяет условию
R % 10^M = 0 // Делится нацело без остатка.

Другими словами, найти последную ненулевую позицию в десятичном предтсавлении числа.

На примере:
970010.000 -> 1
970000.000 -> 4
970000.001 -> -3

Задача стоит иммено в поиске оптималного решения в плане времени вычислений.
Какие будут соображения?
...
Рейтинг: 0 / 0
Задачка из области математики.
    #39419032
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mikron,
1. Переводим в стандартное представление 0.уууExxx.
2. Результат = xxx- количество знаков yyy.
...
Рейтинг: 0 / 0
Задачка из области математики.
    #39419039
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mikronНа примере:
970010.000 -> 1
970000.000 -> 4
970000.001 -> -3
Видишь ли... например, последнее из значений не может быть представлено в виде double по IEEE754 точно таким. Максимально близкое значение - это 0x412D9A200083126F = 970000,001000000047497451305389. Что наводит на мысль, что минус три как бы не очень правильный результат...

Так что если ориентироваться не на значение, а на его представление - то, наверное, наиболее оптимальным будет именно получение строкового представления и обработка полученной строки с целью выявления той самой "точки отсечения".
...
Рейтинг: 0 / 0
Задачка из области математики.
    #39419142
mikron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Akina,

Это только пример для наглядности.
Пусь для начала число будет точно представимым.
...
Рейтинг: 0 / 0
Задачка из области математики.
    #39419150
mikron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaТак что если ориентироваться не на значение, а на его представление - то, наверное, наиболее оптимальным будет именно получение строкового представления и обработка полученной строки с целью выявления той самой "точки отсечения".

Я не уверен, что точно представляю себе как работает форматирование / создание строкового / десятичного представления, но в моём представлении для начала придётся вычислить log10(R)
и последователно извлекать значения до достижения остатком опредлённой epsilon.
Можно ли сделать это быстрее?
...
Рейтинг: 0 / 0
Задачка из области математики.
    #39419221
д0kХ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mikronAkinaТак что если ориентироваться не на значение, а на его представление - то, наверное, наиболее оптимальным будет именно получение строкового представления и обработка полученной строки с целью выявления той самой "точки отсечения".

Я не уверен, что точно представляю себе как работает форматирование / создание строкового / десятичного представления, но в моём представлении для начала придётся вычислить log10(R)
и последователно извлекать значения до достижения остатком опредлённой epsilon.
Можно ли сделать это быстрее?

нужно начинать с того , что отрицательная мантиса говорит о том
что число меньше 1 .
и вобще числа нужно приводить к номализованному виду.

но....
математически нормализованный вид x . ]xxx e y
по стандарту IEEE 754 не всегда проходит по точности , там есть свои
заморочки и исключения для чисел с мантисой близкой к 1 .
и для вычислений может использоваться вид xx . [xx e y-1

ваши примеры в нормализованом виде :
970000.001 = 9.70000001 e 5
...
Рейтинг: 0 / 0
Задачка из области математики.
    #39419225
д0kХ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
д0kХmikronпропущено...


Я не уверен, что точно представляю себе как работает форматирование / создание строкового / десятичного представления, но в моём представлении для начала придётся вычислить log10(R)
и последователно извлекать значения до достижения остатком опредлённой epsilon.
Можно ли сделать это быстрее?

нужно начинать с того , что отрицательный порядок говорит о том
что число меньше 1 .
и вобще числа нужно приводить к номализованному виду.

но....
математически нормализованный вид x.xxx e y
по стандарту IEEE 754 не всегда проходит по точности , там есть свои
заморочки и исключения для чисел с мантисой близкой к 1 .
и для вычислений может использоваться вид xx.xx e y-1

ваши примеры в нормализованом виде :
970000.001 = 9.70000001 e 5

прошу прощения ято то я туплю к концу дня , исправился .
...
Рейтинг: 0 / 0
Задачка из области математики.
    #39419415
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mikronПусь для начала число будет точно представимым.Если округлять не надо, то есть мысль, как это сделать для чисел от 0 до 1. Любая отрицательная степень двойки записывается в десятичной системе счисления так, что количество цифр после точки равно показателю (без минуса). Например, 2 -3 = 0.125, 3 цифры после точки. И так со всеми:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
2 0    = 1
2 -1   = 0.5
2 -2   = 0.25
2 -3   = 0.125
2 -4   = 0.0625
2 -5   = 0.03125
2 -6   = 0.015625
2 -7   = 0.0078125
2 -8   = 0.00390625
2 -9   = 0.001953125
2 -10  = 0.0009765625
2 -11  = 0.00048828125
2 -12  = 0.000244140625
2 -13  = 0.0001220703125
2 -14  = 0.00006103515625
2 -15  = 0.000030517578125
2 -16  = 0.0000152587890625
2 -17  = 0.00000762939453125
2 -18  = 0.000003814697265625
2 -19  = 0.0000019073486328125
2 -20  = 0.00000095367431640625
2 -21  = 0.000000476837158203125
2 -22  = 0.0000002384185791015625
2 -23  = 0.00000011920928955078125
2 -24  = 0.000000059604644775390625
2 -25  = 0.0000000298023223876953125
2 -26  = 0.00000001490116119384765625
2 -27  = 0.000000007450580596923828125
2 -28  = 0.0000000037252902984619140625
2 -29  = 0.00000000186264514923095703125
2 -30  = 0.000000000931322574615478515625
2 -31  = 0.0000000004656612873077392578125
2 -32  = 0.00000000023283064365386962890625
2 -33  = 0.000000000116415321826934814453125
2 -34  = 0.0000000000582076609134674072265625
2 -35  = 0.00000000002910383045673370361328125
2 -36  = 0.000000000014551915228366851806640625
2 -37  = 0.0000000000072759576141834259033203125
2 -38  = 0.00000000000363797880709171295166015625
2 -39  = 0.000000000001818989403545856475830078125
2 -40  = 0.0000000000009094947017729282379150390625
...
Любое double-число от 0 до 1 -- это сумма некоторых отрицательных степеней двойки. Тогда просто ищем самую отрицательную степень двойки в числе, это и даёт нам количество десятичных цифр после точки. Код на C++:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
#include <assert.h>
#include <string.h>

typedef unsigned char byte_t;

enum sign_t {_sign_plus = 0, _sign_minus = 1};

// мантисса (significand) содержит 53 двоичных цифры
const int _significand_len = 53; // = DBL_MANT_DIG из <float.h>

// в таком виде с числом удобно работать
struct unpacked_double_t {
  sign_t sign;
  byte_t significand[_significand_len]; // мантисса
  int exponent; // показатель
};

// double -- в формате IEEE 754 (почти на всех платформах)
unpacked_double_t unpack_double(double x) {
  // получаем битовое представление x
  unsigned long long x_bits;
  memcpy(&x_bits, &x, sizeof(double)); // уважаем strict aliasing

  unpacked_double_t result;

  // распаковываем мантиссу (кроме старшей цифры, она не хранится явно)
  for (int i = 0; i < _significand_len - 1; i++) {
    result.significand[_significand_len - 1 - i] = (x_bits >> i) & 0x1;
  }

  int biased_exponent = (x_bits >> 52) & 0x7ff; // 11 бит
  assert(biased_exponent != 2047); // бесконечности и NAN-ы (not a number) не рассматриваем
  if (biased_exponent > 0) {
    // x -- нормализованное число
    result.significand[0] = 1;
    result.exponent = biased_exponent - 1023;
  } else {
    // x -- денормализованное число (возможно, ноль)
    result.significand[0] = 0;
    result.exponent = 1 - 1023;
  }

  result.sign = static_cast<sign_t>(x_bits >> 63);

  return result;
}

int min_decimal_exponent(double x) {
  assert((0 < x) && (x <= 1));
  unpacked_double_t ux = unpack_double(x);
  // ищем последнюю единицу в мантиссе
  for (int i = _significand_len - 1; ; i--) {
    assert(i >= 0); // хотя бы одна единица должна быть, потому что число ненулевое
    if (ux.significand[i] == 1) {
      return ux.exponent - i;
    }
  }
}

int main() {
  // эти числа точно представимы типом double (в отличие от какого-нибудь 0.1)
  assert(min_decimal_exponent(1) == 0);
  assert(min_decimal_exponent(0.125) == -3); // 2**-3
  assert(min_decimal_exponent(0.1796875) == -7); // 2**-3 + 2**-5 + 2**-6 + 2**-7
  return 0;
}
...
Рейтинг: 0 / 0
Задачка из области математики.
    #39419488
mikron
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов,

Спасибо за детальный ответ. Ваше должно работать для всех вещественнух чисел за исключением натуральных. Таким образом для полного решения необходимо только найти log10(R) целую часть / ограниченнум с низу.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Задачка из области математики.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]