2010-04-29 3 views
4

Я делаю некоторые пользовательские сериализации, и для того, чтобы сэкономить некоторое пространство, я хочу сериализовать десятичные знаки как int, если возможно, значение мудрое. Производительность вызывает беспокойство, поскольку я имею дело с большим объемом данных. Текущий метод, который я использую:Определить, может ли десятичная цифра быть сохранена как int32

if ((value > Int32.MinValue) && (value < Int32.MaxValue) && ((valueAsInt = Decimal.ToInt32(value)) == value)) 
{ 
    return true; 
} 

Можно ли улучшить это?

+0

Вы продолжаете говорить о производительности, но я не вижу никаких критериев или конкретных требований. Откуда вы знаете, что этот метод работает недостаточно эффективно? Насколько вы ожидаете увидеть улучшение? Как вы узнаете, достигли ли вы этого? – Aaronaught

+0

@aaronaught Я не говорю, что этот метод работает недостаточно, но это не значит, что он не может быть более эффективным. Для объема данных, которые я имел, при сериализации и анализе того, что происходит, этот фрагмент кода занимал 4% процессорного времени. Все, что меньше, является улучшением. При этом я не являюсь экспертом по внутренним работам по представлению числа или исполнению IL, поэтому из-за недостатка знаний в этой области может быть место для улучшения. – anchandra

+0

«Производительность» также может быть измерена в зависимости от продолжительности работы. Если он использует только 4% CPU, вы можете многопоточно использовать его для более эффективного использования процессора и завершения работы. Или я неправильно понял, и этот код занял 4% от общего использования ЦП (может быть, около 100%)? –

ответ

1

Есть ли у вас отрицательные значения? Я предполагаю, что да, так как у вас есть проверка MinValue, иначе вы можете пропустить ее. Вы даже можете использовать unsigned int, который позволит вам преобразовать больше ваших двойных значений в int.

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

+0

Я могу иметь любые значения с любым количеством десятичных знаков. Точность является большой проблемой – anchandra

+0

Это на самом деле очень хорошая точка. Я исследую этот аспект. Спасибо – anchandra

+0

В зависимости от характера ваших номеров/требований вы также можете рассмотреть использование коротких, int и long, или даже double и float (но будьте осторожны с потерей точности).Преобразование займет больше времени, так как вам нужно будет определить оптимальный тип, но это сэкономит место. Если вашим узким местом является пространство или скорость передачи (например, медленное подключение к Интернету), а не центральный процессор, это может быть жизнеспособным. –

1

Ваши критерии признания недействительными являются:

1) Является ли это больше, чем MaxValue?

2) Он меньше, чем MinValue?

3) Имеет ли он дробный компонент?

Похоже, вы их покрыли. Моя реализация будет:

public bool IsConvertibleToInt(decimal value) 
{ 
    if(value > int.MaxValue) 
     return false; 

    if(value < int.MinValue) 
     return false; 

    if(Math.Floor(value) < value && Math.Ceiling(value) > value) 
     return false; 

    return true; 
} 
+0

Мое решение работает, мне было интересно, можно ли его ускорить. Спасибо – anchandra

0

Вы бы не быть в состоянии просто сделать что-то вроде:

if(Decimal.ToInt32(value) == value) 
{ 
    return true; 
} 

Не специалист по .net, но я думаю, что должно быть все это было бы нужно. Кроме того, ваши два оператора сравнения должны быть «или равны», так как значения min/max также действительны.

Редактировать: Как указано в комментарии, это создаст исключение. Вы можете попытаться поймать исключение и вернуть false, но в этот момент, скорее всего, будет намного быстрее выполнить тестирование min/max самостоятельно.

+1

@Kitsune: Это вызывает исключение, если значение слишком велико. – RedFilter

+0

@ Kitsune: Это проблема производительности, а не функциональности. Мое текущее решение работает правильно, но я хочу посмотреть, могу ли я улучшить его производительность. – anchandra

+0

@anchandra: Да, поэтому я не рекомендовал это делать вместо этого, поскольку он, вероятно, будет медленнее и, вероятно, не будет более читаемым. – Kitsune

1

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

return (value == (Int32)value); 

запомнить Кроме того, если if оператор просто возвращает логическое значение, вы можете просто вернуть сравнение. Только это может сделать его быстрее (если компилятор уже не оптимизирует для этого). Если вы должны использовать, если заявление, вы можете так же сделать это:

if (value == (Int32)value) 
    { 
     //Do stuff... 
    return true; 
    } 
    else 
    { 
     //Do stuff... 
     return false; 
    } 

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

+1

@smoore: Это вызывает исключение, если значение слишком велико. – RedFilter

+0

Черт, ты прав! –

+0

@OrbMan: Небезопасно ли это трюк и явное литье? –

0

Нет необходимости в значении «ValueAsInt =». Я считаю (Decimal.ToInt32 (value) == value)) получает тот же результат с одним меньшим назначением. Вы используете valueAsInt как некоторый выходной параметр?

+0

Мне нужен он как выходной параметр, но вопрос в том, могу ли я определить значение int более эффективным способом – anchandra

1

Это зависит от того, сколько десятичных разрядов у вас есть или действительно беспокоит. Если вы могли бы сказать, что мне только до 3 десятичных знаков, тогда наибольшее число, которое вы можете сохранить в int32, это int.MaxValue/1000. Если вы работаете только с положительными числами, вы можете получить большее число с помощью uint. В любом случае способ сделать это состоит в том, чтобы последовательно резервировать пространство для десятичной дроби и использовать * 1000 для их кодирования и/1000 для декодирования их в/из десятичного.

+0

Я не могу установить ограничение на точность, к сожалению – anchandra

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