2010-07-14 2 views
3

У меня есть проблемы с преобразованием из двойных десятичных:Преобразование двойного в десятичной

public class CartesianCoordinates 
    { 
     public int LatitudeHours { get; set;} 
     public int LatitudeMinutes { get; set; } 
     public int LatitudeSeconds { get; set; } 
     public GeoDirectionLongtitude LongitudeDirection { get; set; } 

     public int LongitudeHours { get; set; } 
     public int LongitudeMinutes { get; set; } 
     public int LongitudeSeconds { get; set; } 
     public GeoDirectionLatitude LatitudeDirection { get; set; } 
    } 

public class DecimalCoordinates 
    { 
     public decimal Latitude { get; set; } 
     public decimal Longitude { get; set; } 
    } 

CartesianCoordinates CartesianCoordinates=new CartesianCoordinates(){LatitudeHours =12,LatitudeMinutes =34,LatitudeSeconds=56 } 

    converterDecimalCoordinates.Latitude = CartesianCoordinates.LatitudeHours + (CartesianCoordinates.LatitudeMinutes + (CartesianCoordinates.LatitudeSeconds/60))/60; 

Почему я получаю 12? Я хочу 12,55

ответ

3

как побочный продукт моей дискуссии с David M и Даниэль Брюкнер under this answer и частично неправильное заявление себе под this answer by Adam, стало ясно, что, к сожалению, все ответы являются лишь частично правильными. То, что происходит это:

// example (all x, y, z ar ints): 
Decimal d = x + y + z/60M; 

// is left to right evaluated as 
Decimal d = x + y + (((Decimal) z)/60M); 

// when doing addition, this is what happens when you add integers and something else: 
Decimal d = x + y + (int) (((Decimal) z)/60M); 

// which will yield a truncated result. 

Результат: что просто добавить 60M или 60.0 в целом заявление, а has been suggested, не (или не может) дают желаемого результата, в зависимости от порядка выполнения утверждение и/или существование сложения/вычитания, как это имеет место в вопросе ОП.

Чтобы исправить это, последовать совету Адама и преобразовать каждый шаг сложение/вычитание для десятичных знаков, использование десятичных знаков все вместе (не очень понятно) или поместить вычисление в небольшой функции, которая принимает десятичные в качестве параметров, заставляя неявное преобразование:

Decimal GetDecimalLatitude(Decimal latitudeHours, Decimal latitudeMinutes, Decimal latitudeSeconds) 
{ 
    return latitudeHours + (latitudeMinutes + (latitudeSeconds/60))/60; 
} 

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

converterDecimalCoordinates.Latitude = GetDecimalLatitude(
    CartesianCoordinates.LatitudeHours, 
    CartesianCoordinates.LatitudeMinutes, 
    CartesianCoordinates.LatitudeSeconds); 
+0

+1 для неявного литья // колпаки для гольфа –

9

Все ваши вычисления являются целыми и округлены (более точно, усечены). Попробуйте заменить литеральные значения 60 на 60m, чтобы заставить десятичный расчет, или 60.0, чтобы заставить двойной расчет (в этом случае вам нужно будет преобразовать в десятичный разряд в конце).

+4

Только примечание, значения не округлены в ожидаемом смысле - более усеченные. 1.99 будет отбрасываться до 1 для int. –

3

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

Update: как отмечено в других постах, это в настоящее время выполняет целочисленное деление - я не был осведомлен о техническом плане, так как вы, я узнал что-то сегодня лол

+1

Для вычисления в десятичной системе требуется только одно десятичное число. Преобразование всех из них - это немного хлопот. – Abel

+0

Честно говоря, я не обращал слишком много внимания на специфику самого расчета, но я понял, что потеря точности была введена из-за целочисленного деления - другие ответы, так как выяснили этот момент. Кроме того, расчеты, подобные этому, часто улучшают читаемость за счет небольшого количества хлопот, хорошая компромиссная ИМО. Я не получаю любви :-) –

+0

Я был неправ, частично, и вы получили любовь (и кредиты +1), которую вы заслуживаете, я расширил комментарии-ответы в ответе ;-) – Abel

7
Int32 x = 10; 

Decimal y = x/4; // Performs an integer devision - result is 2.0 
Decimal z = x/4M; // Performs a decimal devision - result is 2.25 

Вы получаете целочисленное удаление, если оба операнда являются целыми числами. Добавив суффикс M к номеру, вы можете явно указать, что число должно интерпретироваться как десятичное число, и поэтому вы получите десятичное представление.

+1

Я регулярно сталкиваюсь с «Десятичным x = 1M * [.. ваш расчет ..] ', который является быстрым и легким способом улучшить удобочитаемость и надежность от случайного редактирования, поставив перед собой конверсионный литерал. – Abel

+0

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

+0

@ Давид М: он действительно работает. Попробуйте этот оператор, он даст 2.5M в 'x':' Decimal x = 1M * 5/2; '* (PS: Теперь я понимаю, что вы имеете в виду: это зависит от расчета и порядка исполнения, возможно, не всегда хорошая идея тогда) *. – Abel

1

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

converterDecimalCoordinates.Latitude = CartesianCoordinates.LatitudeHours + (CartesianCoordinates.LatitudeMinutes + (CartesianCoordinates.LatitudeSeconds/60))/(decimal)60; 
Смежные вопросы