Почему не работает сложение больших и малых чисел с плавающей точкой?

В общем решаю задачу и не пойму почему при командах A и D координаты не изменяются.

Начальные координаты (x = 0,001 а.с.; y = 0). Тем не менее, необходимо учитывать координаты с точностью до метра. Напишите программу для управления, где каждое нажатие W, S, A или D изменяет соответствующую координату на 1 метр. (1 а. е. — единица измерения расстояния, приблизительно равна 1.496e+11 метров). Координаты должны выводиться в метрах.

#include <iostream>
#include <string>
#include <cmath>

using namespace std;

int main()
{
  float au = 149597870700.0;
  string step;
  string north = "W";
  string south = "S";
  string west = "A";
  string east = "D";

  float x = 1.0e-3 * au;
  float y = 0.0f * au;
  
  while (true)
  {
      cout << "Марсаход находится на позиции " << x << ", " << y << ", введите команду: ";
      cin >> step;
      if (step == "W") y += 6.684e-12;
      else if (step == "S") y -= 6.684e-12;
      else if (step == "A") x -= 6.684e-12;
      else if (step == "D") x += 6.684e-12;
  }

  return 0;
}

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

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

Давайте прикинем... Итак, значение x примерно 1.496e+8. Значение изменения порядка 7e-12. Т.е. вы суммириует (распишем полностью:

149600000.000000000000
        0.000000000007

Т.е. чтобы увидеть результат, нужна точность представления числа в 20 знаков. Просто прикиньте, если бы это были целые числа - сколько битов бы потребовалось для хранения 20-значного числа? Даже 64 не хватило бы. Т.е. даже double с этим не справился бы. А уж float...

Вот что пишут в Википедии о doubleЖ

Числа двойной точности с плавающей запятой эквивалентны по точности числу с 15-17 значащими десятичными цифрами (в среднем 16,3) в диапазоне примерно от 10−308 до 10308.

А вот о float:

Числа одинарной точности с плавающей запятой эквивалентны по точности числу с 7-8 значащими десятичными цифрами (в среднем 7,6) в диапазоне от 10-38 до примерно 1038.

Как видите, до 20 тут очень далеко.

→ Ссылка