деление на 100 не равно умножению на 0.01

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

берем число 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++ не свойствены законы математики?

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701, компилятор не догадывается, что вы хотите получить, нужно явно задавать желаемый тип float  d = (float)f/100;

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

c умноженим догадывается а с делением нет :)

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

О, сколько нам открытий чУдных..

Не нравится С++, пишите на Бейсике или Паскале.

Этот вопрос уже не раз разжовывался на форуме.

 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

или так:
d = f/100.0

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

вообщем в таких случаях компилятору надо указывать ".0", т. е. должна быть точка

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701 пишет:

вообщем в таких случаях компилятору надо указывать ".0", т. е. должна быть точка

Считаю, что лучше писать перед операцией желаемый тип данных. Если делитель будет неизвестной переменной, то ноль вам просто некуда будет дописать.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

В стандарте вроде как все правила и рекомендации есть.. не, "не наш метод"? :)

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

dimax пишет:

Считаю, что лучше писать перед операцией желаемый тип данных. Если делитель будет неизвестной переменной, то ноль вам просто некуда будет дописать.

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

а это не есть good, когда мало памяти, по учебникку надо ставить "делтель . 0"

спасибо всем за ответы

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701, никакой "ещё одной переменной" не нужно.  Пример я вам написал в #1.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

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; выводит правильно

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

dimax пишет:

Valera19701, никакой "ещё одной переменной" не нужно.  Пример я вам написал в #1.

В принципе - я тоже за явное приведение типов.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701,  квотить про температуру не буду. Этот пример ясен. Плохо вы читали учебники на которые ссылаетесь, или учебники плохие :) Есть такое понятие как переменная по умолчанию. Эта переменная int16_t  Попробуйте без указания типа решить такую задачку :

byte a=255,b=255,c=255;
void setup() {
Serial.begin(9600);

long n= a*b*c;
Serial.print(n);
}

void loop() {

}

Полкчите вы 16581375 в ответ? Не получите.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Valera19701 пишет:
деление на 100 не равно умножению на 0.01

Это точно! Не равно!

Valera19701 пишет:
получается языку c++ не свойствены законы математики?
Нет, конечно! А с каокого перпепуду они должны быть ему свойственны? "Часы не обязаны всё показывать!".

Проблема на самом деле не в том, что языку c++ не свойствены законы математики, а в том, что Valera19701 не свойственны законы языка С++!

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

ЕвгенийП пишет:

Проблема на самом деле не в том, что языку c++ не свойствены законы математики, а в том, что Valera19701 не свойственны законы языка С++!

только пару месяцев как начал программировать, и то как хобби

ну а насчет своественности

это как 2*2=3 и добавляем костыль если вы умножаете 2 на 2 то к ответу прибавьте 1 :)

как то так

Клапауций 777
Offline
Зарегистрирован: 21.11.2015

Valera19701 пишет:

это как 2*2=3 и добавляем костыль если вы умножаете 2 на 2 то к ответу прибавьте 1 :)

т.е. ты не понимаешь, почему 25.89 = 26.00 ?

а, если 25.89 округлить до целых, сколько будет?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

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

Клапауций 777
Offline
Зарегистрирован: 21.11.2015

Valera19701 пишет:

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

ну, и зачем эти жёлтые сенсационные разоблачения С++, если понимаешь

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

Клапауций 777 пишет:

ну, и зачем эти жёлтые сенсационные разоблачения С++, если понимаешь

просто показал что не обязательно делить на 100.0 а можно умножить на 0.01

Клапауций 777
Offline
Зарегистрирован: 21.11.2015

Valera19701 пишет:

просто показал что не обязательно делить на 100.0 а можно умножить на 0.01

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

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

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

Клапауций 777 пишет:

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

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

не прочувствовал, калькулятор был назывался "железный феликс"

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Valera19701 пишет:

только пару месяцев как начал программировать, и то как хобби

ну а насчет своественности

это как 2*2=3 и добавляем костыль если вы умножаете 2 на 2 то к ответу прибавьте 1 :)

Вот я и пытаюсь Вам помочь, потому что Вы только начинаете.

Вы не поняли главной мысли моего поста, а без понимания её Вы никогда не будете нормально программировать.

А мысль была такая: язык программирования - это формальный язык, определяемый своим описанием. Он точно соответсвует своему описанию и абсолютно не обязан соответсвовать Вашим, моим или ещё чьим-то представлениям о математике, биологии или балете. Язык программированния такой, как он описан. У него свои правила. Их надо знать и применять. Вот и всё.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Valera19701 пишет:

получается языку c++ не свойствены законы математики?

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

На самом деле существует масса математических дисциплин, и в каждой из них законы свои.

Язык С, как и другие алгоритмические языки, использует законы математической дисциплины, которая называется Численные методы. Просто Вы не только не знаете ни самих численных методов, ни используемых ими законов, но даже не догадываетесь о существовании такой дисциплины.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

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

Не заметно.

Ибо оно заключается в простом выводе: КАЖДОЕ(!) действие должно ГДЕ_ТО сохранять результат. Даже если вы накатали все в один оператор.

Ваше float = ((digitalRead()<<8)+digitalRead())/100; это 3(ТРИ) отдельных действия:

1. tmpInt = digitalRead()<<8 .. почему "int"? а потому что стандарт прописывает, что тип результата выводится из операндов операции. В данном случае базовый тип есть int .. у константы 8.

2. tmpInt = tmpInt + digitalRead(); и снова в итоге получаем int

3. tmpInt = tmpInt/100 одно целое делим на другое .. и тоже ЦЕЛОЕ. Результат конечно же целое число.

и вот только потом(!) этот результат и будет преобразован во float, ибо сложить его надо туда.

оператор "=" -- это не математический знак. Это действие(!) по перемещению данных в памяти с места на место. Только и всего.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

что то все от темы ушли, был задан вопрос, почему в описании языка на простое математическое действие как деление с плавающей запятой (не надо только расписывать что все математические действия производятся через сложение) надо ставить костыль, а при умножении не надо

http://arduino.ru/Reference/Float

пример с переменной Z, вот и все,  а вы тут демагогию развели

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701, похоже вы так ничего и не поняли из того, что вам объясняли.

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

dimax, я все понял, в сообщении #24 я же не поставил знак вопроса, а подвел итог беседы , или это не понятно?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701, раз понятно, объясните тогда такой пример:

int a=32767;
long n= a+2;

Чему равно n , и почему оно этому равно?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

-32767

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701, а почему не 32769 ?

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

потому что int двухбайтовое число 2 в степени 16 равно 65536 а так как оно может быть отрицательным и положительным то получается 2 в степени 15 , один бит уходит на это

еще есть вопросы?, а то я себя в 45 лет чувствую учеником за партой :)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701, есть :)  А как получить  32769  ? Мне нужно что б в лонг n было 32769

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

вы меня еще и на типы разводить будете

вот

1 long a=32767;
2 long n= a+2;

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701 , а зачем вы меняете заданные задачей типы данных? Считайте, тип данных "a" и "n" изменить невозможно.

Говорю же вам, вы ничего не поняли!

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

так и написали бы что а менять нельзя

вот

long n= (unsigned int)a+2;

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701, Ну наконец :) теперь вы понимаете, что для любой математической операции программист обязан задать тип и разрядность предпологаемых данных?   Если тип данных не задан, то он будет по умолчанию  int16_t. 

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

я это понимал когда синклеры на z80 собирал, мне просто интересен ход мыслей Страуструпа и все

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Valera19701, если бы вы это сразу понимали, то не задали бы свой вопрос :-)

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

dimax пишет:

Valera19701, если бы вы это сразу понимали, то не задали бы свой вопрос :-)

если бы я не понимал, я бы не ответил на ваши вопросы, да и опять же, как вы говорите что все задается в начале типы данных, но вот сами дали пример где надо ставить костыль с другим указателем типа и это как я вижу вы считаете праввильным?

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

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Да ничего он не "рушит" .. все верно. Пример с float z просто нагляднее, но он меньше объясняет .. И Страуструп, опирался на имеющийся функционал С. Поверьте, я немножко "в курсе" процесса разработки С++ у Страуструпа "в то время". :)

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Valera19701 пишет:

так и написали бы что а менять нельзя

вот

long n= (unsigned int)a+2;


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

Valera19701
Valera19701 аватар
Offline
Зарегистрирован: 18.10.2015

kisoft прочтите внимательно последние пять постов, и адресуйте это не мне

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

kisoft, пример просто в качестве примера) Придумайте другой, если этот не нравится :)

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

А, я понял, учимся плохому, продолжайте дальше. Говнокод он такой, говнокод.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

kisoft, почему сразу говнокод? Ну пусть будет long n= (int32_t) a+2; Важно, что бы человек понял, что проблемы ждут не только при делении, а при любых операциях.

Клапауций 777
Offline
Зарегистрирован: 21.11.2015

смешались в кучу, кони люди - зачем приводить примеры с диапазонами значений, если сабж о целых и дробных числах и математических действиях с ними?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Valera19701 пишет:

если бы я не понимал, я бы не ответил на ваши вопросы, да и опять же, как вы говорите что все задается в начале типы данных, но вот сами дали пример где надо ставить костыль с другим указателем типа и это как я вижу вы считаете праввильным?

Я, кстати, тоже считаю такой код правильным и искренне не понимаю, почему Вы называете его костылем.

Цитата:

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

Давайте физику не трогать - она здесь совершено ни при чем.

В математике, безусловно, есть постулаты, только они в любой математичесткой дисциплине свои. Ответьте, например, с точки зрения математических постулатов на два вопроса:

1. Есть ли решение у уравнения x^2 = -1, где символом "^" обозначена операция возведения в степень?

2. Правда ли, что a*b = b*a, гда знаком "*" обозначена операция умножения?

Valera19701, Ваша проблема в том, что Вы постулаты из одного раздела математики пытаетесь применить в другом, - для которого они не просто не являются постулатами, а вообще не выполняются.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

dimax пишет:

kisoft, почему сразу говнокод? Ну пусть будет long n= (int32_t) a+2; Важно, что бы человек понял, что проблемы ждут не только при делении, а при любых операциях.


Я уже объяснил почему, потому что нельзя смешивать беззнаковые и знаковые переменные, мало того, что это может привести к проблемам при поиске багов, это ещё и говорит о том, что при проектировании допущена ошибка.
В последнем варианте, почему int32_t, а не long? Какая цель? Типа сэкономить на спичках? Не знаю как сделает компилятор, но чисто как это выглядит, получится два приведения типов, сначала к int32_t, потом результат к long. Это нормально?
Надеюсь понятно объяснил. Мне нет резона докапываться, но тему потом кто нибудь прочтет и сделает так же. Уж поверьте моему многолетнему опыту. Впрочем, настаивать не буду, у каждого свои грабли.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

kisoft пишет:
...это ещё и говорит о том, что при проектировании допущена ошибка.

Золотые слова!

Сколько замечательных идей было убито ошибками стадии проектирования, причем зачастую авторы попыток реализаций этих идей искренне не понимали наличия такой ошибки, а потому в извечной дилемме "бага или фича" считалм "багу" "фичей".

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

kisoft пишет:
В последнем варианте, почему int32_t, а не long? Какая цель? Типа сэкономить на спичках? Не знаю как сделает компилятор, но чисто как это выглядит, получится два приведения типов, сначала к int32_t, потом результат к long. Это нормально?

 long и int32_t  разве это не одно и тоже ??? 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

andriano, "багофича", есть такое слово :)