DT
Dec. 23, 2018, 12:33 p.m.

Простой калькулятор

На самом деле, задание действительно простое. Проблема есть лишь в выводе результата.

            double result;
            if(ui->radioButton_s->isChecked())
            {
                result=oper1+oper2;
                if (result>=qInf() or result<=-qInf())
                    ui->label_res->setText("Близость к бесконечности - ошибка");
                else
                    ui->label_res->setText(tr("%1").arg(result));

Участок кода, где результат выводиться в QLabel. Оба оператора, естественно, тоже double. Так вот, если при таком раскладе попытаться сложить слишком маленькие числа, то оно попросту начнет их округлять:

Если же чуть изменить метод вывода на

ui->label_res->setText(QString::number(result,'g',39));

, то результат перестанет округляться, но начнет появляться непонятный "мусор".

Что это за "мусор", почему он появляется, и как, в таком случае, нормально выводить ответ?

10% refund of hotel reservation amount on Booking
10% refund of hotel reservation amount on Booking
We offer a link with a 10% return on the amount of the order when booking a hotel through Booking
5
DT

Через некоторое время я осознал, что проблема не столько в выводе, сколько при самом переводе из текста в число. Почему одно число, что было без плавающей точки, перевелось нормально, а второе так ужасно? Почему так происходит?

0

Добрый день!

Потому, что все компьютеры имеют ограничения по количеству разрядов для чисел с плавающей запятой. И всегда точность будет ограничена разрядностью.

Существуют специальные библиотеки для проведения расчётов с числами, для которых требуется большая точность, чем позволяет разрядность ПК.

Но в вашем случае не имеет смысла использовать подобную библиотеку, вы же не научные изыскания ведёте.

В общем смиритесь, в определённых ситуациях всегда будет некоторое округления. Это особенность архитектуры ПК и ограничений с количество разрядов для каждой конкретной архитектуры. Единственное решение - это задавать разрядность для округления.

0
DT

Извиняюсь, но это даже не округление, это ерунда какая-то. Почему при переводе строки "0.344" через .toDouble(), оно в итоге получает число 0.343999999999...? В смысле, ладно, хорошо, я смирился. Но когда преподаватель спросит "А почему КОНКРЕТНО так происходит?", что мне ему ответить?

0

Нет никакой ерунды, просто архитектура компьютера не позволяет корректно хранить число с плавающей запятой 0.344

Это дробь, а дроби имеют свойство быть бесконечными в плане разрядности. Компьютер просто не может корректно представить это число.

Просто есть числа, чтобы корректно хранить которые требуется больше чем 64 разряда. Дроби как раз часто и относятся к таким числам.

Почитайте про числа с плавающей точкой, мантиссу числа и т.д. а также про разрядность компьютеров и т.д. И попробуйте написать в двоичном виде число 0.344, сами увидите, что разрядов вам не хватит, поэтому и получите что-то вроде 0.343999999999..

0

Я сам уже не помню, как правильно представлять дроби в двоичном представлении (давно этим не занимался в силу отсутствия необходимости), но по факту проблема в том, что двоичное представление ограничено количеством разрядов, а некоторые дроби для своего представления требуют больше разрядов, чем есть в распоряжении ПК, вот и выскакивают такие глюки. Это погрешность из разряда нормы. Если хотите более полного объяснения, то Вам потребуется прочитать про формирование числа с плавающей точкой и попытаться вручную, на листе, например, попытаться написать 0.344 в двоичном виде, например, для ограничения в 32 разряда. Когда разряды закончатся, то попытайтесь привести это число в десятичный вид, получите 0.343999999999..

0

Comments

Only authorized users can post comments.
Please, Log in or Sign up
July 22, 2019, 7:26 a.m.
Pavel K.

Qt - Test 001. Signals and slots

  • Result:68points,
  • Rating points-1
o
July 22, 2019, 6:26 a.m.
oksik193

C++ - Test 001. The first program and data types

  • Result:80points,
  • Rating points4
VD
July 21, 2019, 11:33 p.m.
Vlad Dolgov

C++ - Test 001. The first program and data types

  • Result:40points,
  • Rating points-8
Last comments
July 21, 2019, 6:03 a.m.
Evgenij Legotskoj

да, наверное, 32-х разрядную поддержку уже давно поа было выкинуть. К слову, у вас много проектов под Android? Часто много где вижу вопросы о том, пишет ли кто-то вообще на Qt под мобильные сист…
July 20, 2019, 2:41 p.m.
Andrej Jankovich

Очень полезная информация, увы уже выкинул поддержку 32 битных бедняг.
July 20, 2019, 9:31 a.m.
Mihailll

Вот так qDebug()<<"position:"<<event->scenePos();
July 20, 2019, 8:49 a.m.
Mihailll

Добрый день. Как можно узнать координату на графической сцене при отпускании клавиши мыши?
Now discuss on the forum
July 22, 2019, 8:41 a.m.
BlinCT

Вот только что нашел в инете, у человека такая же ошибка. Вроде бы таже самая проблема https://stackoverflow.com/questions/37633709/how-to-create-qtquick-window-outside-the-main-thread…
July 22, 2019, 3:58 a.m.
Evgenij Legotskoj

Добрый день! Нужен совет сообщества по разработке функционала проверки орфографии. Одна из идей - добавить проверку орфографии при наборе текста статей. Полагаю, что наиболее аде…
July 22, 2019, 3:01 a.m.
Evgenij Legotskoj

Возможно, если при сохранении файла установить права доступа на файл. Что-то такое должно быть у QFile
July 22, 2019, 3:01 a.m.
Evgenij Legotskoj

Я отрисовываю квадрат в его локальной системе координат от верхнего левого угла (-30,-30) до его правого нижнего угла (30,30). Поэтому мне нужно указать размеры объекта через boundingRect()…
July 20, 2019, 11:04 a.m.
Mihailll

Так и с ресурсами работает QImage image(":/Images/Images/1.png");
Looking for a Job?
5,000.00 руб. - 15,000.00 руб.
Дизайнер
Moskovskiy, Moscow, Russia
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

EVILEG
About
Services
Join us
© EVILEG 2015-2019
Recommend hosting TIMEWEB