У меня были следующие проблемы для ответа @Lalit Kumars,
ORA-19202: Error occurred in XML processing
ORA-00904: "SUCCESS": invalid identifier
ORA-06512: at "SYS.DBMS_XMLGEN", line 288
ORA-06512: at line 1
19202. 00000 - "Error occurred in XML processing%s"
*Cause: An error occurred when processing the XML function
*Action: Check the given error message and fix the appropriate problem
Решение:
WITH char_cols AS
(SELECT /*+materialize */ table_name, column_name
FROM cols
WHERE data_type IN ('CHAR', 'VARCHAR2'))
SELECT DISTINCT SUBSTR (:val, 1, 11) "Searchword",
SUBSTR (table_name, 1, 14) "Table",
SUBSTR (column_name, 1, 14) "Column"
FROM char_cols,
TABLE (xmlsequence (dbms_xmlgen.getxmltype ('select "'
|| column_name
|| '" from "'
|| table_name
|| '" where upper("'
|| column_name
|| '") like upper(''%'
|| :val
|| '%'')' ).extract ('ROWSET/ROW/*') ) ) t
ORDER BY "Table"
/
Для этого нужно всего лишь разделение и округление:
int value = 30;
int factor = 16;
int nearestMultiple =
(int)Math.Round(
(value / (double)factor),
MidpointRounding.AwayFromZero
) * factor;
Будьте осторожны, используя эту технику. Перегрузка Math.Round(double)
считает, что злой мутант MidpointRounding.ToEven
является наилучшим поведением по умолчанию, хотя то, что мы все узнали раньше в школе, это то, что CLR вызывает MidpointRounding.AwayFromZero
. Например:
var x = Math.Round(1.5); // x is 2.0, like you'd expect
x = Math.Round(0.5); // x is 0. WAT?!
16*((n+8)/16)
- это формула, которую вы хотите, если, в частности, вы хотите конвертировать 8 до 16 (она одинаково близка к 0 по 16, поэтому невозможно решить, как ее преобразовать, основываясь исключительно на «ближайшем множестве», концепция, вы должны решить! -), и, конечно, последовательно от 24 до 32, от 40 до 48 и т. д. Используйте +7
вместо +8
, если вы предпочитаете преобразовывать 8 в 0, а не в 16 (и последовательно от 24 до 16 и т. Д.).
Использовать общий X
в вместо hardcoded 16
, тогда формула X*((n+X/2)/X)
(с тем же условием, что и в предыдущем абзаце, если X
четно).
Редактирование: нет необходимости возиться с плавающей запятой числа, как предлагают другие ответы, но вы do должны умножаться на X
(что я ошибочно пропустил).
Случай немного сложнее, если множественное число меньше 1. Я написал эту общую функцию:
public float NearestRound(float x, float delX)
{
if (delX < 1)
{
float i = (float)Math.Floor(x);
float x2 = i;
while ((x2 += delX) < x) ;
float x1 = x2 - delX;
return (Math.Abs(x - x1) < Math.Abs(x - x2)) ? x1 : x2;
}
else {
return (float)Math.Round(x / delX, MidpointRounding.AwayFromZero) * delX;
}
}
/* Sample:
x: 101 multiple:2 NearestRound -> 102
x: 107 multiple:2 NearestRound -> 108
x: 100.9 multiple:2 NearestRound -> 100
x: 1 multiple:0.25 NearestRound -> 1
x: 1.35 multiple:0.25 NearestRound -> 1.25
x: 1.77 multiple:0.25 NearestRound -> 1.75
x: 1.9 multiple:0.25 NearestRound -> 2 */
Раунды посередине в направлении + ∞
int RoundNearest16(int value)
{
return (value + 8) & ~0xF;
}
В случае округления до ближайшего кратного поплавка вы можете использовать это:
public static float convert(float value, float multipleOf)
{
return (float) Math.Round((decimal)value / (decimal)multipleOf, MidpointRounding.AwayFromZero) * multipleOf;
}
Затем вы можете использовать функцию следующим образом:
Console.WriteLine("Convert 10.723: " + convert(10.723f, 0.5f)); // 10.5