2009-11-25 2 views
2

Я пытаюсь уменьшить неявные преобразования типов, когда я использую named constants в моем коде. Например, вместо использованияНеявные преобразования типов в выражениях int to double

const double foo = 5; 

Я хотел бы использовать

const double foo = 5.0; 

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

const double halfFoo = foo/2; 

и т.д. Это 2 оценивается как целое и неявно преобразуется? Должен ли я использовать 2.0 вместо этого?

+1

Поскольку это помечено как C++: пример в вопросе довольно прост. Для реальных программ (и когда вы не используете встроенные функции) я подчеркиваю использование точного типа и явных конструкторов. Неоднозначное или неявное построение и преобразование являются причинами ошибок, которые трудно найти, а также хитов производительности и правильной правильности программы. – justin

ответ

5

2 неявно преобразован в двойной, потому что foo является двойным. Вы должны быть осторожны, потому что если foo было, скажем, целым, целочисленным делением, то результат будет сохранен в halfFoo.

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

+0

Вторая мысль, а как насчет сравнения? Как сравнивать двойной, чтобы быть < or > 0? Мне интересно, использовать ли 0 или 0.0 – Anonymous

+0

. Я бы использовал 0.0, просто чтобы остаться в привычке, хотя в этом случае это действительно неважно. –

+3

@Person: конверсии происходят во время компиляции, а не во время выполнения, поэтому (время выполнения) не является проблемой. Если LHS сравнения производит поплавок или двойной, RHS должен быть плавающей или двойной константой, для ясности для людей, читающих код. Но для компилятора существует незначительная разница. –

1

Это известно как Type Coercion Википедия имеет приятный немного об этом:..

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

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

...

Такое поведение следует использовать с осторожностью, так как могут возникнуть непредвиденные последствия. Данные могут быть потеряны, когда представления с плавающей запятой преобразуются в интегральные представления, поскольку дробные компоненты значений с плавающей запятой будут усечены (округлены вниз). И наоборот, преобразование из интегрального представления в плавающую точку также может потерять точность, поскольку тип с плавающей запятой может быть неспособным точно представлять целое число (например, float может быть типом одиночной точности IEEE 754, который не может представлять integer 16777217 точно, в то время как 32-разрядный целочисленный тип может). Это может привести к ситуациям, таким как сохранение одного и того же целочисленного значения на две переменные типа integer и тип real, которые возвращают false, если сравнивать их для равенства.

В случае C и C++ значение выражения интегральных типов (т. Е. Longs, integers, shorts, chars) является наибольшим интегральным типом в выражении. Я не уверен, но я предполагаю, что что-то подобное происходит (при условии, что значения с плавающей запятой «больше», чем целые) с выражениями, включающими числа с плавающей запятой.

3

Строго говоря, то, что вы пытаетесь достичь, кажется контрпродуктивным.

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

const double foo = 5; /* better */ 

чем

const double foo = 5.0; /* worse */ 

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

if (foo > 0) 

лучше

if (foo > 0.0) 

, потому что, опять же, бывший более типа независимой.

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

Это правда, что в некоторых случаях у вас нет другого выбора, кроме как явно выразить тип (например, использовать 2.0 вместо 2 и т. Д.). Но обычно это можно делать только тогда, когда это действительно нужно. Почему кто-то сделал это без реальной потребности, это вне меня.

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