Глобальные функции
Внешний вид
Общие сведения
Функции, вынесенные в глобальную видимость через объект Code, позволяют централизованно управлять логикой форматирования данных.
Это избавляет от необходимости дублировать код в каждом отдельном макете и обеспечивает единообразие расчетов во всех отчетах.
Rounding.RoundBase()
Предназначена для гибкого округления числовых значений.
В отличие от стандартных функций, она поддерживает работу с отрицательными разрядами и округление до значащих цифр.
Входные параметры
value(Double) - исходное число для обработки;digits(Object)- при
Mode = 1- количество знаков после запятой (положительное) или до запятой (отрицательное); - при
Mode = 0- количество значащих цифр;
- при
mode(Object) - режим работы:1(ToDecimalPlace) - десятичное округление;0(ToSignificantPlace) - значащие цифры.
Выходные параметры
String- возвращает строковое представление числа.
Алгоритм
Функция работает по методу Away From Zero (округление от нуля).
Режим 1 (десятичное округление):
- вычисляется множитель;
- число умножается на множитель, округляется до целого и делится обратно;
- при положительном n результат форматируется с фиксированным количеством нулей после запятой.
Режим 0 (значащие цифры):
- определяется порядок числа через десятичный логарифм;
- вычисляется масштабный коэффициент, чтобы оставить ровно
nцифр; - число масштабируется, округляется и возвращается в исходный порядок;
- результат преобразуется в компактную строку (удаляются лишние нули в конце).
Примеры использования в дизайнере-конструкторе
| Исходное значение | Синтаксис в соответствии с формулой =Code.Rounding.RoundBase(x, n, m)
|
Результат |
|---|---|---|
| 12345 | =Code.Rounding.RoundBase(ReportItems!variable.Value, 2, 1)
|
12345,00 |
| 12345.00 | =Code.Rounding.RoundBase(ReportItems!variable.Value, 0, 1)
|
12345 |
| 12345.01 | =Code.Rounding.RoundBase(ReportItems!variable.Value, -2, 1)
|
12300 |
| 555.55 | =Code.Rounding.RoundBase(ReportItems!variable.Value, 1, 0)
|
600 |
Предварительный вариант на VB.NET
Public Function RoundBase(ByVal xValue As Double, ByVal nDigits As Integer, ByVal mMode As Integer) As String
If xValue = 0 Then Return "0"
'Проверка аргумента nDigits, является ли пустым, остутствующим в БД или пустой строкой
Dim nDigitsFlag As Boolean = True
If nDigits Is Nothing OrElse IsDBNull(nDigits) OrElse String.IsNullOrEmpty(nDigits.ToString().Trim()) Then
nDigitsFlag = False
End If
'Проверка аргумента mMode, является ли пустым, остутствующим в БД или пустой строкой
Dim mModeFlag As Boolean = True
If mMode Is Nothing OrElse IsDBNull(mMode) OrElse String.IsNullOrEmpty(mMode.ToString().Trim()) Then
mModeFlag = False
End If
'Если хотя бы один из параметров (nDigits или mMode) отсутствует, возвращается исходное число xValue
If (nDigitsFlag = False) Or (mModeFlag = False)
Return xValue
End If
If mMode = 1 Then
' Округление до n знаков после запятой
' В отличие от стандартной функции Math.Round(value, digits, MidpointRounding.AwayFromZero)
' может работать с отрицательными digits за счет сдвига
' Вычисление множителя
Dim factor As Double = Math.Pow(10, nDigits)
' Свдиг запятой на расстояние множителя, округление до целого, обратный сдвиг
' Направление сдвига зависит от знака (+-) в nDigits
Dim result As Double = Math.Round(xValue * factor, 0, MidpointRounding.AwayFromZero) / factor
' Форматирование результата (либо до целого(0), либо по положительному nDigits)
Return result.ToString("F" & Math.Max(0, nDigits))
End If
If mMode = 0 Then
' Округление до n значащих цифр
' Определение порядка числа (до запятой)
Dim scale As Double = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(xValue))) + 1 - nDigits)
' Свдиг запятой влево (уменьшение порядка числа), округление, сдвиг вправо (увеличение порядка числа)
Dim result As Double = Math.Round(xValue / scale, 0, MidpointRounding.AwayFromZero) * scale
' Форматирование результата в компактную строку (удаление лишних нулей, научная нотация)
Return result.ToString("G")
End If
' При некорректном значении режима mMode
Return ""
End Function
Итоговый вариант на С#
public class Rounding
{
public string RoundBase(double value, int digits, RoundMode mode)
{
if (value == 0)
return "0";
double result;
switch (mode)
{
case RoundMode.ToDecimalPlace:
double factor = Math.Pow(10, digits);
result = Math.Round(value * factor, 0, MidpointRounding.AwayFromZero) / factor;
return result.ToString("F" + Math.Max(0, digits));
case RoundMode.ToSignificantPlace:
double scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(value))) + 1 - digits);
result = Math.Round(value / scale, 0, MidpointRounding.AwayFromZero) * scale;
return result.ToString("G");
default:
throw new ArgumentOutOfRangeException(nameof(mode), "Некорректный режим округления");
}
}
public string RoundBase(double value, int digits, int mode) => RoundBase(value, digits, (RoundMode)mode);
}