2010-09-13 3 views
1

Это, наверное, что-то очень простое, но я не получаю ожидаемых результатов. Я прошу прощения, если это глупый вопрос, я просто не понимаю, что делать.простой вопрос о назначении float для int

Самый простой способ объяснить это с некоторым кодом:

int var = 2.0*4.0; 

NSLog(@"%d", 2.0*4.0);//1 
NSLog(@"%d", var);//2 

if ((2.0*4.0)!=0) {//3 
    NSLog(@"true"); 
} 

if (var!=0) {//4 
    NSLog(@"true"); 
} 

Это производит следующий вывод:

0 //1 
8 //2 
true //3 
true //4 

Тот, что я не понимаю, это линия //1. Почему все остальные конвертируют (я предполагаю, что правильное слово «casting», пожалуйста, поправьте меня, если я ошибаюсь) float в int, но внутри NSLog этого не происходит. Это имеет какое-то отношение к форматированию строки %d, и это суетливо (из-за отсутствия лучшего слова)?

ответ

4

Вы говорите NSLog, что вы передаете это целое число в формате @"%d" спецификатора, но вы на самом деле не давая ему целое число; вы даете ему значение с плавающей запятой с двойной точностью (8.0, как это бывает). Когда вы обращаетесь к NSLog, его поведение не определено, и вы получаете неожиданные результаты, подобные этому.

Не лгите NSLog. Если вы хотите, чтобы преобразовать результат 2.0*4.0 в целое перед печатью, вы должны сделать это явно:

NSLog(@"%d", (int)(2.0*4.0)); 

Если, вместо этого, вы хотите, чтобы распечатать результат 2.0*4.0 как число двойной точности с плавающей точкой , вам нужно использовать другой спецификатор формата:

NSLog(@"%g", 2.0*4.0); 

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

0

Строка формата %d ожидает десятичное число, что означает целое число 10, а не плавающая точка. То, что вы хотите есть %f, если вы пытаетесь получить его, чтобы распечатать 8.0

+0

Yup. '% d' означает« десятичный », а не« двойной ». –

+0

Или '% g', который интеллектуально выбирает между фиксированным десятичным и научным форматом. – Potatoswatter

0

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

Основная информация; Убедитесь, что вы передаете переменные правильного типа во втором (и последующем) параметре.

2

В примерах 2, 3 и 4 поплавок либо присваивается int (который преобразует его), либо сравнивается с int (который также преобразует его). В 1, однако, вы передаете float в качестве аргумента функции. Функция printf позволяет всем аргументам после строки исходного формата быть любого типа, поэтому это действительно. Но поскольку компилятор не знает, что вы имеете в виду, что он является int (помните, вы ничего не сделали, чтобы сообщить компилятору), float передается как значение с плавающей запятой. Когда printf видит спецификатор форматирования %d, он выводит достаточно байтов для int из списка аргументов и интерпретирует эти байты как int. Эти байты выглядят как целое число 0.

3

Во-первых, вы никогда не использовали float s в своей программе. Это double s.

Во-вторых, аргументы NSLog, printf и любит не автоматически преобразуются в то, что вы задаете с помощью %d или %f. Он следует стандартным правилам продвижения для нетипизированных аргументов. См. the ISO specification, sec 6.5.2.2.6 and 6.5.2.2.7. Обратите внимание на супер странное правило, что внутри этих функций,

  • в float автоматически произведен в double,
  • и любое целое число меньше, чем int повышается до int. (См 6.3.1.1.2)

Таким образом, строго говоря, спецификация %f не показывая float, но в double. См. Тот же документ, гл. 7.19.6.1.8.

Обратите также внимание на то, что в вашем случае 1 и 3 промо-акции должны быть double.

+0

+1 для 'no float - only double' –

+0

Вы используете float вместо double, если хотите сэкономить место, как правило, для больших массивов (не несколько переменных стека). –

Смежные вопросы