деление на 100 не равно умножению на 0.01
- Войдите на сайт для отправки комментариев
Пт, 27/11/2015 - 14:28
берем число float с двумя знаками после запятой , умножаем на 100
напрмер float c = 25.89;
int16_t f = c * 100
получаем целое число f =2589 - тут все нормально
пытаемся вернуть число float обратно
float d = 0;
d = f/100 - и получаем 26.00 - неправильное значение , почемуто округляется
d = f * 0.01 - и получаем правильное значение 25.89
получается языку c++ не свойствены законы математики?
Valera19701, компилятор не догадывается, что вы хотите получить, нужно явно задавать желаемый тип float d = (float)f/100;
c умноженим догадывается а с делением нет :)
О, сколько нам открытий чУдных..
Не нравится С++, пишите на Бейсике или Паскале.
Этот вопрос уже не раз разжовывался на форуме.
или так:
d = f/100.0
вообщем в таких случаях компилятору надо указывать ".0", т. е. должна быть точка
вообщем в таких случаях компилятору надо указывать ".0", т. е. должна быть точка
Считаю, что лучше писать перед операцией желаемый тип данных. Если делитель будет неизвестной переменной, то ноль вам просто некуда будет дописать.
В стандарте вроде как все правила и рекомендации есть.. не, "не наш метод"? :)
Считаю, что лучше писать перед операцией желаемый тип данных. Если делитель будет неизвестной переменной, то ноль вам просто некуда будет дописать.
для этого надо добавлять еще одну переменную или делать вычисление при выводе результата,
а это не есть good, когда мало памяти, по учебникку надо ставить "делтель . 0"
спасибо всем за ответы
Valera19701, никакой "ещё одной переменной" не нужно. Пример я вам написал в #1.
dimax , хорошо вот пример с I2C
float temperature = 0;
float temperature = (Wire.read() << 8 | Wire.read())/100; - выводит 26.00, округляет
int16_t temperature = 0;
temperature = (Wire.read() << 8 | Wire.read());
вычисление при выводе результата Serial.printiln((float)temperature/100); выводит правильно
float temperature = 0;
temperature = (Wire.read() << 8 | Wire.read())/100.0; выводит правильно
Valera19701, никакой "ещё одной переменной" не нужно. Пример я вам написал в #1.
В принципе - я тоже за явное приведение типов.
Valera19701, квотить про температуру не буду. Этот пример ясен. Плохо вы читали учебники на которые ссылаетесь, или учебники плохие :) Есть такое понятие как переменная по умолчанию. Эта переменная int16_t Попробуйте без указания типа решить такую задачку :
Полкчите вы 16581375 в ответ? Не получите.
Это точно! Не равно!
Проблема на самом деле не в том, что языку c++ не свойствены законы математики, а в том, что Valera19701 не свойственны законы языка С++!
Проблема на самом деле не в том, что языку c++ не свойствены законы математики, а в том, что Valera19701 не свойственны законы языка С++!
только пару месяцев как начал программировать, и то как хобби
ну а насчет своественности
это как 2*2=3 и добавляем костыль если вы умножаете 2 на 2 то к ответу прибавьте 1 :)
как то так
это как 2*2=3 и добавляем костыль если вы умножаете 2 на 2 то к ответу прибавьте 1 :)
т.е. ты не понимаешь, почему 25.89 = 26.00 ?
а, если 25.89 округлить до целых, сколько будет?
да понимаю я все, что по умолчанию округляет до целого числа, так как тяжело ворочать с числами с плавающей запятой, и т. д., это так, ради забавы
да понимаю я все, что по умолчанию округляет до целого числа, так как тяжело ворочать с числами с плавающей запятой, и т. д., это так, ради забавы
ну, и зачем эти жёлтые сенсационные разоблачения С++, если понимаешь
ну, и зачем эти жёлтые сенсационные разоблачения С++, если понимаешь
просто показал что не обязательно делить на 100.0 а можно умножить на 0.01
просто показал что не обязательно делить на 100.0 а можно умножить на 0.01
хм. вроде со школы все знают, что умножать проще, чем делить.
или, ты сразу калькулятором начал пользоваться и не прочувствовал хардкор деления на бумаге вручную
хм. вроде со школы все знают, что умножать проще, чем делить.
или, ты сразу калькулятором начал пользоваться и не прочувствовал хардкор деления на бумаге вручную
не прочувствовал, калькулятор был назывался "железный феликс"
только пару месяцев как начал программировать, и то как хобби
ну а насчет своественности
это как 2*2=3 и добавляем костыль если вы умножаете 2 на 2 то к ответу прибавьте 1 :)
Вот я и пытаюсь Вам помочь, потому что Вы только начинаете.
Вы не поняли главной мысли моего поста, а без понимания её Вы никогда не будете нормально программировать.
А мысль была такая: язык программирования - это формальный язык, определяемый своим описанием. Он точно соответсвует своему описанию и абсолютно не обязан соответсвовать Вашим, моим или ещё чьим-то представлениям о математике, биологии или балете. Язык программированния такой, как он описан. У него свои правила. Их надо знать и применять. Вот и всё.
получается языку c++ не свойствены законы математики?
Это беда не С и не математики, а исключительно - школьного курса математики, который внушает ученикам, что мол существует одна единая математика и у нее одни и те же законы.
На самом деле существует масса математических дисциплин, и в каждой из них законы свои.
Язык С, как и другие алгоритмические языки, использует законы математической дисциплины, которая называется Численные методы. Просто Вы не только не знаете ни самих численных методов, ни используемых ими законов, но даже не догадываетесь о существовании такой дисциплины.
Не заметно.
Ибо оно заключается в простом выводе: КАЖДОЕ(!) действие должно ГДЕ_ТО сохранять результат. Даже если вы накатали все в один оператор.
Ваше float = ((digitalRead()<<8)+digitalRead())/100; это 3(ТРИ) отдельных действия:
1. tmpInt = digitalRead()<<8 .. почему "int"? а потому что стандарт прописывает, что тип результата выводится из операндов операции. В данном случае базовый тип есть int .. у константы 8.
2. tmpInt = tmpInt + digitalRead(); и снова в итоге получаем int
3. tmpInt = tmpInt/100 одно целое делим на другое .. и тоже ЦЕЛОЕ. Результат конечно же целое число.
и вот только потом(!) этот результат и будет преобразован во float, ибо сложить его надо туда.
оператор "=" -- это не математический знак. Это действие(!) по перемещению данных в памяти с места на место. Только и всего.
что то все от темы ушли, был задан вопрос, почему в описании языка на простое математическое действие как деление с плавающей запятой (не надо только расписывать что все математические действия производятся через сложение) надо ставить костыль, а при умножении не надо
http://arduino.ru/Reference/Float
пример с переменной Z, вот и все, а вы тут демагогию развели
Valera19701, похоже вы так ничего и не поняли из того, что вам объясняли.
dimax, я все понял, в сообщении #24 я же не поставил знак вопроса, а подвел итог беседы , или это не понятно?
Valera19701, раз понятно, объясните тогда такой пример:
Чему равно n , и почему оно этому равно?
-32767
Valera19701, а почему не 32769 ?
потому что int двухбайтовое число 2 в степени 16 равно 65536 а так как оно может быть отрицательным и положительным то получается 2 в степени 15 , один бит уходит на это
еще есть вопросы?, а то я себя в 45 лет чувствую учеником за партой :)
Valera19701, есть :) А как получить 32769 ? Мне нужно что б в лонг n было 32769
вы меня еще и на типы разводить будете
вот
1
long
a=32767;
2
long
n= a+2;
Valera19701 , а зачем вы меняете заданные задачей типы данных? Считайте, тип данных "a" и "n" изменить невозможно.
Говорю же вам, вы ничего не поняли!
так и написали бы что а менять нельзя
вот
long n= (unsigned int)a+2;
Valera19701, Ну наконец :) теперь вы понимаете, что для любой математической операции программист обязан задать тип и разрядность предпологаемых данных? Если тип данных не задан, то он будет по умолчанию int16_t.
я это понимал когда синклеры на z80 собирал, мне просто интересен ход мыслей Страуструпа и все
Valera19701, если бы вы это сразу понимали, то не задали бы свой вопрос :-)
Valera19701, если бы вы это сразу понимали, то не задали бы свой вопрос :-)
если бы я не понимал, я бы не ответил на ваши вопросы, да и опять же, как вы говорите что все задается в начале типы данных, но вот сами дали пример где надо ставить костыль с другим указателем типа и это как я вижу вы считаете праввильным?
в чем мой вопрос не правилен, просто есть постулаты математики, физики, и т. д. и разработанный намного позже язык рушит некоторые из них, как говорится нужно в голове держать, что в математике так можно, а в програмировании надо разделять все, целые числа или с плавающей запятой
Да ничего он не "рушит" .. все верно. Пример с float z просто нагляднее, но он меньше объясняет .. И Страуструп, опирался на имеющийся функционал С. Поверьте, я немножко "в курсе" процесса разработки С++ у Страуструпа "в то время". :)
так и написали бы что а менять нельзя
вот
long n= (unsigned int)a+2;
Плохой вариант, смешиваешь беззнаковые и знаковые значения, это плохо кончится однажды
kisoft прочтите внимательно последние пять постов, и адресуйте это не мне
kisoft, пример просто в качестве примера) Придумайте другой, если этот не нравится :)
А, я понял, учимся плохому, продолжайте дальше. Говнокод он такой, говнокод.
kisoft, почему сразу говнокод? Ну пусть будет long n= (int32_t) a+2; Важно, что бы человек понял, что проблемы ждут не только при делении, а при любых операциях.
смешались в кучу, кони люди - зачем приводить примеры с диапазонами значений, если сабж о целых и дробных числах и математических действиях с ними?
если бы я не понимал, я бы не ответил на ваши вопросы, да и опять же, как вы говорите что все задается в начале типы данных, но вот сами дали пример где надо ставить костыль с другим указателем типа и это как я вижу вы считаете праввильным?
Я, кстати, тоже считаю такой код правильным и искренне не понимаю, почему Вы называете его костылем.
в чем мой вопрос не правилен, просто есть постулаты математики, физики, и т. д. и разработанный намного позже язык рушит некоторые из них, как говорится нужно в голове держать, что в математике так можно, а в програмировании надо разделять все, целые числа или с плавающей запятой
Давайте физику не трогать - она здесь совершено ни при чем.
В математике, безусловно, есть постулаты, только они в любой математичесткой дисциплине свои. Ответьте, например, с точки зрения математических постулатов на два вопроса:
1. Есть ли решение у уравнения x^2 = -1, где символом "^" обозначена операция возведения в степень?
2. Правда ли, что a*b = b*a, гда знаком "*" обозначена операция умножения?
Valera19701, Ваша проблема в том, что Вы постулаты из одного раздела математики пытаетесь применить в другом, - для которого они не просто не являются постулатами, а вообще не выполняются.
kisoft, почему сразу говнокод? Ну пусть будет long n= (int32_t) a+2; Важно, что бы человек понял, что проблемы ждут не только при делении, а при любых операциях.
Я уже объяснил почему, потому что нельзя смешивать беззнаковые и знаковые переменные, мало того, что это может привести к проблемам при поиске багов, это ещё и говорит о том, что при проектировании допущена ошибка.
В последнем варианте, почему int32_t, а не long? Какая цель? Типа сэкономить на спичках? Не знаю как сделает компилятор, но чисто как это выглядит, получится два приведения типов, сначала к int32_t, потом результат к long. Это нормально?
Надеюсь понятно объяснил. Мне нет резона докапываться, но тему потом кто нибудь прочтет и сделает так же. Уж поверьте моему многолетнему опыту. Впрочем, настаивать не буду, у каждого свои грабли.
Золотые слова!
Сколько замечательных идей было убито ошибками стадии проектирования, причем зачастую авторы попыток реализаций этих идей искренне не понимали наличия такой ошибки, а потому в извечной дилемме "бага или фича" считалм "багу" "фичей".
long и int32_t разве это не одно и тоже ???
andriano, "багофича", есть такое слово :)