Простейшая программа во Flex 4.5. Неправильно суммирует числа типа Number

Суть программы в том что бы при нажатии на кнопку она выводила в текстовое результат сложения 3,2 +1,1. По идее программа должна вывести 4,3. Но она выводит 4,300000000000001. С другими числами все ок 5,1+6,1=11,2
upd: вопрос написал а код вставляется не правильно. Извините покажу скриншот и в комменте ниже дам код частями.
s15.radikal.ru/.../1110/90/b84490e53120.jpg
Подскажите где ошибка?

👍НравитсяПонравилось0
В избранноеВ избранном0
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

А вы попробуйте произвольную дробь представить суммой отрицательных степеней двойки (0.5, 0.25, 0.125, 0.0625 и так далее), посмотрим, как это у вас получится, а уж потом будем определять, кто налажал — они в реализации или вы — в знании элементарной теории.

Обычно в качетсве ответа оставляют следующие ссылки:
en.wikipedia.org/wiki/IEEE_754

steve.hollasch.net/.../ieeefloat.html

так же еще добавляют: программа вам не врет, все так и есть. Это Сишный printf, плюсовый cout тихонько округляет числа после 6-7 знака после запятой... чтобы выглядели числа правильно.

Плюсовый cout тихонько округляет числа после 6-7 знака после запятой...

www.cplusplus.com/...rs/setprecision

Конечно:) я же не говорю что нельзя форматировать выходящий stream.
Я об этом: ideone.com/asXSZ и например: ideone.com/vFdRT

Я об этом: ideone.com/asXSZ и например: ideone.com/vFdRT

#include <stdio.h>

int main()
{
fprintf(stdout, “3.2+1.1=%f\n”, 3.2+1.1);
fprintf(stdout, “3.2+1.1=%g\n”, 3.2+1.1);
fprintf(stdout, “3.2+1.1=%e\n”, 3.2+1.1);
return 0;

}

Я имел ввиду, что:
Когда новичок пишет программу на плюсах он видит в результате: 4.3. И думает что все ок и не задумывается о представлении чисел с плавающей точкой.

Когда пишет, например, на Java(или в данном случае Flex), то получает на выводе, то как действительно представлены числа и ищет ошибку в трех соснах.

Когда новичок пишет программу на плюсах он видит в результате: 4.3. И думает что все ок и не задумывается о представлении чисел с плавающей точкой.

На C тоже самое.

fprintf(stdout, “3.2+1.1=%f\n”, 3.2+1.1);
fprintf(stdout, “3.2+1.1=%g\n”, 3.2+1.1);
fprintf(stdout, “3.2+1.1=%e\n”, 3.2+1.1);
fprintf(stdout, “3.2+1.1=%20.20g\n”, 3.2+1.1);
--------------------------------------------------------
3.2+1.1=4.300000
3.2+1.1=4.3
3.2+1.1=4.300000e+00

3.2+1.1=4.30000000000000071054

В мэйнстрим-программировании математика как бы сбивает с толку, правда?

А что, может и так сойдет? Или кто-то в наше-то время, падающих самолетов и улетающих в молоко спутников, постесняется очевидно ложного результата в листинге? (привет тем, кто написал: «это не ошибка». Если это не позорный баг, то надо понимать, что это фишечка язычочка?)

Младшеклассник складывать двухциферные числа умеет, а взрослые дяденьки — нет. Зато дяденьки старательно замесили и подготовили для этих ваших Rich Internet Applications г****код. Объехать его можно, только позвав для сложения двухциферных чисел Math.round.

Поступает такой смышленый младшеклассник в кружок «умелый проггер», невинно тискает клавиш на входе, а оно уже полезло, и внезапно! на выходе. =) г****код!

Младшеклассника высаживает, он скомпрометирован, и _все_ сейчас подумают, что напрограммить такое мог только г****кодер? Не все так подумают. С вами всё в порядке, младшеклассники. Это не вы нагадили в код. Это вас плохие дяденьки учат программировать. То, что вы добавите туда еще и свои ошибки по неопытности, ничего не изменит. Как говорят в народе, inverted: (кашу маслом не испортишь).

Или кто-то в наше-то время, падающих самолетов и улетающих в молоко спутников, постесняется очевидно ложного результата в листинге? (привет тем, кто написал: «это не ошибка».

Перед использованием floating point нужно читать user disclaimer от Intel.

Самолет, доверь мы Интелу управление, таки упадет? =)

A propo, отвлекаясь от слоя штукатурки HLL, и глядя на голый процессор, мы увидим, он ведь не умеет ничего, кроме как складывать единицы и позиционно сдвигать на своих регистрах.

Можно из-за плеча младшеклассника понаблюдать, как он складывает двухциферные числа. Удивительно, он совмещает позиции запятых и целочисленно складывает. Какой умный младшеклассник... непуганный еще нырятельной, или как там, плавательной арифметикой...

Загляни через плечо процессору как он совмещает позиции запятых и складывает двоичные числа.

Младшеклассник игнорирует запятые. Иначе при сложении двух чисел обязан будет поставить у суммы две запятые. Но вот сюрприз, при сложении чисел младшеклассник подразумевает действия с цифрами. А запятая не цифра. Процессор тоже не знает, что такое запятая или отрицательное число. Он даже вычитать не умеет.

Самолет, доверь мы Интелу управление, таки упадет? =)

Я не видел использование float в mission/life critical проектах, кроме как для визуализации и приблизительных вычислений.

Вам лучше видно, из QNX... что там у нас mission/life critical projects.

Но общество станет лучше, если молодые люди будут получать правду. Даже обучаясь программированию. Нельзя использовать неправдивые, вводящие в заблуждение термины, или двусмысленные термины. Например, демократия или floating point system (не повернется язык сказать: FP арифметика). Может, тогда самолеты не будут падать и во имя демократии нельзя будет бомбить.

Но общество станет лучше, если молодые люди будут получать правду. Даже обучаясь программированию.

Правда в Ваших руках, только Вы ей пользуетесь избирательно. Только почему-то потерялась нормализация чисел, перевод их внутри, в процессоре, в extended precision формат, а может компилятором будет использоваться SSE2, тогда промежуточным будет что? float или может double? А потом да, задача на четверть такта, сложить два бинарных числа.

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

«Над созданием „Булавы“ МИТ трудится уже более десяти лет, но из 11 пусков лишь один можно уверенно признать успешным. ... компьютер „Булавы“ оказался неспособен корректировать отклонение ракеты от курса.... Николай Калистратов, гендиректор ПО „Севмаш“, на котором строятся подлодки для „Булавы“, прямо сказал, что „проблемы ракеты не в пиропатронах, а в качестве программирования“.»
expert.ru/...ya_rentgenolog

Насколько я понимаю, траектория это численное интегрирование. Я не уверен, что у нас остались специалисты, спокойно пишущие целочисленный код, (самый эффективный и верифицируемый). Хм, и я в общем-то, даже не уверен, что компьютер Булавы не запрограммировали джависты ;)

Специалисты есть, просто им нечего делать в рамках этих первобытных структур.

Как впрочем было и 20 лет назад, когда советские операционные системы делались из MS-DOS шестнадцатиричным редактором путем русификации строчек на английском языке.

Но 20 лет назад некуда особо было бежать, а сейчас выбор обширен.

«Над созданием „Булавы“ МИТ трудится уже более десяти лет, но из 11 пусков лишь один можно уверенно признать успешным. ... компьютер „Булавы“ оказался неспособен корректировать отклонение ракеты от курса.... Николай Калистратов, гендиректор ПО „Севмаш“, на котором строятся подлодки для „Булавы“, прямо сказал, что „проблемы ракеты не в пиропатронах, а в качестве программирования“.»

Судя по всему это просто critical проект, без приставки life or mission.

«Фобос-Грунт» не вышел на отлетную траекторию.
www.newsru.com/...11/fobos_2.html

www.interfax.ru/...=1446&id=215891

«В сложившейся ситуации, возможно, произошел сбой системы звездной ориентации или ошибка в системном коде программы, которая должна была управлять этим оборудованием», — сказал собеседник агентства.

... Вторая возможная причина — сырой софт. Как отметил источник, два года назад, когда планировался старт аппарата «Фобос-Грунт», программисты жаловались на недоработки программного обеспечения работающим с навигационным оборудованием. Тем не менее утверждалось, что к нынешнему старту все ошибки были исправлены.

-------------------
Программирование, как математическая прикладная дисциплина, умерло.

(математик, как известно, утверждает только то, что может доказать)

Роскосмосу не удалось установить связь с межпланетной станцией Фобос-Грунт

korrespondent.net/...iej-fobos-grunt

Казалось бы причём тут fp? :)

Очень сложный для понимания комментарий, предполагающий сопутствующее применение психотропных веществ.

На Stack Overflow этот вопрос задается ежедневно. Людьми, не умеющими пользоваться поиском.

Посмотрите вот это:

stackoverflow.com/...er-problem-flex

Не понятно как в этих условиях написать такую простую программу как калькулятор.

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

А у вас есть ссылка на то как это реализовано? Виндовый калькулятор то нормально считает.

Кнут. Искусство программироватия. Том 2.

ru.wikipedia.org/...нная_арифметика

Вот, кстати интересный экземляр.

www.ttmath.org/...line_calculator

Там есть эта библиотека в исходниках.

Виндовый калькулятор тоже теряет точность ввиду ограниченного количества бит, имеющихся под мантиссу, сложите им к примеру 10 + 4.3000000000000000000000000000001

3.2+1.1 он считает нормально.

Он округляет результат прежде, чем показать его пользователю. То же нужно сделать и вам.

на Stack Overflow показано как округлить но тогда оно округляет и 3,22+1,11 до 4,3, а хочется видеть 4,33. Надо как-то дополнительно считать количество знаков после запятой?

Самый банальный способ — взять десятичный логарифм от рассматриваемого значения, отбросить дробную часть, прибавить 1. Получится число значащих цифр слева от десятичной точки (или отрицательное в случае если значение сильно меньше единицы). Исходя из него выбрать точность округления, так чтобы не округлить чересчур сильно.

Как вариант — все числа хранить умноженными на десятку в степени. Например на 100. Проводить с ними все арифметические действия. А перед непосредственным употреблением, например, передачей параметром, делить на 100.

Это прокатит только с + и — . Умножение придется делить на 10000. А в делении вообще толку не будет.

Делить на 100 надо результат. Т.е. (100*3,2 + 100*1,1)/100 = 4,3

Это прокатит только с + и — . Умножение придется делить на 10000. А в делении вообще толку не будет.

Это называется fixed point арифметика: сложение a+b=c, вычитание c-b=a, умножение a*b=c/100, деление c*100/b=a.

ru.wikipedia.org/...ованная_запятая

Делить на 100 надо результат. Т.е. (100*3,2 + 100*1,1)/100 = 4,3

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

И какие конкретно оcобенности мешают представлению чисел 3.2, 1.1 & 4.3?

Я не нашел по указанной тобой ссылке ответ на мой вопрос. Тебе так сложно сказать какие конкретно особенности ты имел в виду?

А 0.3 случайно не будет представлен как 3 * 10 ^ −1 без всяких округлений и периодических дробей?

Оно будет нормализовано в 0.3.

Залежить від реалізації

www.codeguru.com/...ad.php?t=323835

Q: But the next program outputs “Expected value” in the Debug build and “Unexpected value” in the Release and I don’t know why.

int main()
{
float a = 0.1;
a*=10;
if (a == 1.0) cout << “Expected value” << endl;

else cout << “Unexpected value” << endl;

return 0;

}

A: In Debug build, the value will get actually stored into the stack variable a before comparison. This conversion from the FPU stack to float corrects the floating point error because of rounding. In a Release build, the variable gets optimised away, and the value on the FPU stack is compared to 1.0 (no conversion to float happens).

float’ы вообще запрещено сравнивать на точное совпадение...

protected function button_clickHandler(event:MouseEvent):void
{
var numTwo:Number = 5.1;
var numFour:Number = 6.1;
var sumInts:Number = addInts(numTwo, numFour);
output.text = numTwo.toString() + " + " + numFour.toString() +" = "+ sumInts;
}
private function addInts( value1:Number, value2:Number ):Number{
var sum:Number = value1 + value2;
return sum;

}

Подписаться на комментарии