билинейная интерполяция просто означает взвешивание значения, основанного на 4 ближайших пикселях, к тому, которое вы изучаете. Весы можно рассчитать следующим образом.
cv::Point2f current_pos; //assuming current_pos is where you are in the image
//bilinear interpolation
float dx = current_pos.x-(int)current_pos.x;
float dy = current_pos.y-(int)current_pos.y;
float weight_tl = (1.0 - dx) * (1.0 - dy);
float weight_tr = (dx) * (1.0 - dy);
float weight_bl = (1.0 - dx) * (dy);
float weight_br = (dx) * (dy);
Ваше окончательное значение рассчитывается как сумма продуктов каждого пикселя с его соответствующим весом
public static string Reverse( string s )
{
char[] charArray = s.ToCharArray();
Array.Reverse( charArray );
return new string( charArray );
}
"Лучший путь" зависит от того, что более важно для Вас в Вашей ситуации, производительности, элегантность, пригодность для обслуживания и т.д.
Так или иначе, вот подход с помощью Массива. Реверс:
string inputString="The quick brown fox jumps over the lazy dog.";
char[] charArray = inputString.ToCharArray();
Array.Reverse(charArray);
string reversed = new string(charArray);
Если строка будет содержать данные Unicode (строго говоря, non-BMP символы) другие методы, которые были отправлены, то повредит его, потому что Вы не можете подкачать порядок высоких и низких суррогатных элементов кода при инвертировании строки. (Больше информации об этом может быть найдено на мой блог .)
следующий пример кода правильно инвертирует строку, которая содержит non-BMP символы, например, "\U00010380\U00010381" (угаритская Буква Alpa, угаритская Бета Буквы).
public static string Reverse(this string input)
{
if (input == null)
throw new ArgumentNullException("input");
// allocate a buffer to hold the output
char[] output = new char[input.Length];
for (int outputIndex = 0, inputIndex = input.Length - 1; outputIndex < input.Length; outputIndex++, inputIndex--)
{
// check for surrogate pair
if (input[inputIndex] >= 0xDC00 && input[inputIndex] <= 0xDFFF &&
inputIndex > 0 && input[inputIndex - 1] >= 0xD800 && input[inputIndex - 1] <= 0xDBFF)
{
// preserve the order of the surrogate pair code units
output[outputIndex + 1] = input[inputIndex];
output[outputIndex] = input[inputIndex - 1];
outputIndex++;
inputIndex--;
}
else
{
output[outputIndex] = input[inputIndex];
}
}
return new string(output);
}
Это оказывается удивительно хитрым вопросом.
я рекомендовал бы использовать Массив. Реверс для большинства случаев, поскольку это кодируется исходно и очень просто поддержать и понять.
Это, кажется, превосходит StringBuilder по характеристикам во всех случаях, которые я протестировал.
public string Reverse(string text)
{
if (text == null) return null;
// this was posted by petebob as well
char[] array = text.ToCharArray();
Array.Reverse(array);
return new String(array);
}
существует второй подход, который может быть быстрее для определенных длин строки который Xor использования.
public static string ReverseXor(string s)
{
if (s == null) return null;
char[] charArray = s.ToCharArray();
int len = s.Length - 1;
for (int i = 0; i < len; i++, len--)
{
charArray[i] ^= charArray[len];
charArray[len] ^= charArray[i];
charArray[i] ^= charArray[len];
}
return new string(charArray);
}
Примечание , Если Вы хотите поддерживать полный набор символов Unicode UTF16 , считало это . И используйте реализацию там вместо этого. Это может быть далее оптимизировано при помощи одного из вышеупомянутых алгоритмов и пробежки строки для чистки его после того, как символы будут инвертированы.
Вот сравнение производительности StringBuilder, Массива. Reverse и метод Xor.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace ConsoleApplication4
{
class Program
{
delegate string StringDelegate(string s);
static void Benchmark(string description, StringDelegate d, int times, string text)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int j = 0; j < times; j++)
{
d(text);
}
sw.Stop();
Console.WriteLine("{0} Ticks {1} : called {2} times.", sw.ElapsedTicks, description, times);
}
public static string ReverseXor(string s)
{
char[] charArray = s.ToCharArray();
int len = s.Length - 1;
for (int i = 0; i < len; i++, len--)
{
charArray[i] ^= charArray[len];
charArray[len] ^= charArray[i];
charArray[i] ^= charArray[len];
}
return new string(charArray);
}
public static string ReverseSB(string text)
{
StringBuilder builder = new StringBuilder(text.Length);
for (int i = text.Length - 1; i >= 0; i--)
{
builder.Append(text[i]);
}
return builder.ToString();
}
public static string ReverseArray(string text)
{
char[] array = text.ToCharArray();
Array.Reverse(array);
return (new string(array));
}
public static string StringOfLength(int length)
{
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++)
{
sb.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))));
}
return sb.ToString();
}
static void Main(string[] args)
{
int[] lengths = new int[] {1,10,15,25,50,75,100,1000,100000};
foreach (int l in lengths)
{
int iterations = 10000;
string text = StringOfLength(l);
Benchmark(String.Format("String Builder (Length: {0})", l), ReverseSB, iterations, text);
Benchmark(String.Format("Array.Reverse (Length: {0})", l), ReverseArray, iterations, text);
Benchmark(String.Format("Xor (Length: {0})", l), ReverseXor, iterations, text);
Console.WriteLine();
}
Console.Read();
}
}
}
Вот результаты:
26251 Ticks String Builder (Length: 1) : called 10000 times.
33373 Ticks Array.Reverse (Length: 1) : called 10000 times.
20162 Ticks Xor (Length: 1) : called 10000 times.
51321 Ticks String Builder (Length: 10) : called 10000 times.
37105 Ticks Array.Reverse (Length: 10) : called 10000 times.
23974 Ticks Xor (Length: 10) : called 10000 times.
66570 Ticks String Builder (Length: 15) : called 10000 times.
26027 Ticks Array.Reverse (Length: 15) : called 10000 times.
24017 Ticks Xor (Length: 15) : called 10000 times.
101609 Ticks String Builder (Length: 25) : called 10000 times.
28472 Ticks Array.Reverse (Length: 25) : called 10000 times.
35355 Ticks Xor (Length: 25) : called 10000 times.
161601 Ticks String Builder (Length: 50) : called 10000 times.
35839 Ticks Array.Reverse (Length: 50) : called 10000 times.
51185 Ticks Xor (Length: 50) : called 10000 times.
230898 Ticks String Builder (Length: 75) : called 10000 times.
40628 Ticks Array.Reverse (Length: 75) : called 10000 times.
78906 Ticks Xor (Length: 75) : called 10000 times.
312017 Ticks String Builder (Length: 100) : called 10000 times.
52225 Ticks Array.Reverse (Length: 100) : called 10000 times.
110195 Ticks Xor (Length: 100) : called 10000 times.
2970691 Ticks String Builder (Length: 1000) : called 10000 times.
292094 Ticks Array.Reverse (Length: 1000) : called 10000 times.
846585 Ticks Xor (Length: 1000) : called 10000 times.
305564115 Ticks String Builder (Length: 100000) : called 10000 times.
74884495 Ticks Array.Reverse (Length: 100000) : called 10000 times.
125409674 Ticks Xor (Length: 100000) : called 10000 times.
кажется, что Xor может быть быстрее для коротких строк.
/id/login_openid
. Начальное повторение: URL разделяется к уровню каталога и = login_openid
. Это будет соответствовать правилу № 2 (строка № 5). Перезапись происходит, и новый URL /id/login_openid.php
, и перезапись переходит к следующему повторению. Повторение № 2 : URL разделяется вниз и = login_openid.php
. Это не будет очень никакие правила КРОМЕ последнего, которое говорит Apache прерываться, запрос (отправьте 403 ответа) - именно так работают Ваши текущие правила.
– LazyOne
23 July 2011 в 18:39
Если Вы хотите играть в действительно опасную игру, то это - безусловно самый быстрый путь существует (приблизительно в четыре раза быстрее, чем Array.Reverse
метод). Это - оперативное обратное использование указатели.
Примечание, что я действительно не рекомендую это ни для какого использования, никогда ( взглянули здесь по некоторым причинам, почему Вы не должны использовать этот метод ), но просто интересно видеть, что это может быть сделано, и что строки не действительно неизменны, как только Вы включаете небезопасный код.
public static unsafe string Reverse(string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}
fixed (char* pText = text)
{
char* pStart = pText;
char* pEnd = pText + text.Length - 1;
for (int i = text.Length / 2; i >= 0; i--)
{
char temp = *pStart;
*pStart++ = *pEnd;
*pEnd-- = temp;
}
return text;
}
}
Попытайтесь использовать Массив. Реверс
public string Reverse(string str)
{
char[] array = str.ToCharArray();
Array.Reverse(array);
return new string(array);
}
Взгляните на статью в Википедии здесь . Они реализуют Строку. Инвертируйте дополнительный метод. Это позволяет Вам писать код как это:
string s = "olleh";
s.Reverse();
Они также используют комбинацию ToCharArray/Reverse, которую предлагают другие ответы на этот вопрос. Исходный код похож на это:
public static string Reverse(this string input)
{
char[] chars = input.ToCharArray();
Array.Reverse(chars);
return new String(chars);
}
Извините за длинное сообщение, но это могло бы быть интересно
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
public static string ReverseUsingArrayClass(string text)
{
char[] chars = text.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
public static string ReverseUsingCharacterBuffer(string text)
{
char[] charArray = new char[text.Length];
int inputStrLength = text.Length - 1;
for (int idx = 0; idx <= inputStrLength; idx++)
{
charArray[idx] = text[inputStrLength - idx];
}
return new string(charArray);
}
public static string ReverseUsingStringBuilder(string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}
StringBuilder builder = new StringBuilder(text.Length);
for (int i = text.Length - 1; i >= 0; i--)
{
builder.Append(text[i]);
}
return builder.ToString();
}
private static string ReverseUsingStack(string input)
{
Stack<char> resultStack = new Stack<char>();
foreach (char c in input)
{
resultStack.Push(c);
}
StringBuilder sb = new StringBuilder();
while (resultStack.Count > 0)
{
sb.Append(resultStack.Pop());
}
return sb.ToString();
}
public static string ReverseUsingXOR(string text)
{
char[] charArray = text.ToCharArray();
int length = text.Length - 1;
for (int i = 0; i < length; i++, length--)
{
charArray[i] ^= charArray[length];
charArray[length] ^= charArray[i];
charArray[i] ^= charArray[length];
}
return new string(charArray);
}
static void Main(string[] args)
{
string testString = string.Join(";", new string[] {
new string('a', 100),
new string('b', 101),
new string('c', 102),
new string('d', 103),
});
int cycleCount = 100000;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingCharacterBuffer(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingCharacterBuffer: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingArrayClass(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingArrayClass: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingStringBuilder(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingStringBuilder: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingStack(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingStack: " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < cycleCount; i++)
{
ReverseUsingXOR(testString);
}
stopwatch.Stop();
Console.WriteLine("ReverseUsingXOR: " + stopwatch.ElapsedMilliseconds + "ms");
}
}
}
Результаты:
Во-первых Вы не должны звонить ToCharArray
, поскольку строка может уже быть индексирована как массив символов, таким образом, это сохранит Вас выделение.
следующая оптимизация должна использовать StringBuilder
для предотвращения ненужных выделений (поскольку строки неизменны, связывание их делает копию строки каждым разом). Для дальнейшей оптимизации этого, мы задаем длину StringBuilder
, таким образом, она не должна будет разворачивать свой буфер.
public string Reverse(string text)
{
if (string.IsNullOrEmpty(text))
{
return text;
}
StringBuilder builder = new StringBuilder(text.Length);
for (int i = text.Length - 1; i >= 0; i--)
{
builder.Append(text[i]);
}
return builder.ToString();
}
Редактирование: Данные о производительности
я протестировал эту функцию и функцию с помощью Array.Reverse
со следующей простой программой, где Reverse1
одна функция, и Reverse2
другой:
static void Main(string[] args)
{
var text = "abcdefghijklmnopqrstuvwxyz";
// pre-jit
text = Reverse1(text);
text = Reverse2(text);
// test
var timer1 = Stopwatch.StartNew();
for (var i = 0; i < 10000000; i++)
{
text = Reverse1(text);
}
timer1.Stop();
Console.WriteLine("First: {0}", timer1.ElapsedMilliseconds);
var timer2 = Stopwatch.StartNew();
for (var i = 0; i < 10000000; i++)
{
text = Reverse2(text);
}
timer2.Stop();
Console.WriteLine("Second: {0}", timer2.ElapsedMilliseconds);
Console.ReadLine();
}
оказывается, что для коротких строк Array.Reverse
метод приблизительно вдвое более быстр, чем тот выше, и для более длинных строк различие является еще более явным. Таким образом, учитывая, что Array.Reverse
метод и более прост и быстрее, я рекомендовал бы использовать это, а не этого. Я оставляю на виду этого здесь только, чтобы показать, что это не способ, которым необходимо сделать это (к моему большому удивлению!)
Должен был отправить рекурсивный пример:
private static string Reverse(string str)
{
if (str.IsNullOrEmpty(str) || str.Length == 1)
return str;
else
return str[str.Length - 1] + Reverse(str.Substring(0, str.Length - 1));
}
[UIFont fontWithName:]
, PostScript/имя шрифта.
– Hari Karam Singh
20 February 2013 в 08:29
Так как мне нравятся несколько ответов - один для использования string.Create
и поэтому высокая производительность и низкое выделение и другой для правильности - использование StringInfo
класс, я решил, что объединенный подход необходим. Это - окончательный строковый метод реверсирования:)
private static string ReverseString(string str)
{
return string.Create(str.Length, str, (chars, state) =>
{
var enumerator = StringInfo.GetTextElementEnumerator(state);
var position = state.Length;
while (enumerator.MoveNext())
{
var cluster = ((string)enumerator.Current).AsSpan();
cluster.CopyTo(chars.Slice(position - cluster.Length));
position -= cluster.Length;
}
});
}
существует еще лучший способ использовать метод класса StringInfo, который пропускает много строковых выделений Перечислителем путем возврата просто индексов.
private static string ReverseString(string str)
{
return string.Create(str.Length, str, (chars, state) =>
{
var position = 0;
var indexes = StringInfo.ParseCombiningCharacters(state); // skips string creation
var stateSpan = state.AsSpan();
for (int len = indexes.Length, i = len - 1; i >= 0; i--)
{
var index = indexes[i];
var spanLength = i == len - 1 ? state.Length - index : indexes[i + 1] - index;
stateSpan.Slice(index, spanLength).CopyTo(chars.Slice(position));
position += spanLength;
}
});
}
Некоторые сравнительные тесты по сравнению с решением LINQ:
String length 20:
LINQ Mean: 2,355.5 ns Allocated: 1440 B
string.Create Mean: 851.0 ns Allocated: 720 B
string.Create with indexes Mean: 466.4 ns Allocated: 168 B
String length 450:
LINQ Mean: 34.33 us Allocated: 22.98 KB
string.Create Mean: 19.13 us Allocated: 14.98 KB
string.Create with indexes Mean: 10.32 us Allocated: 2.69 KB
Greg Beech опубликовал unsafe
вариант, который действительно настолько быстр, насколько это возможно (это ин-плейс реверс); но, как он указал в своем ответе, это совершенно катастрофическая идея.
Тем не менее, я удивлен, что существует такой консенсус, что Array.Reverse
является самым быстрым методом. Существует еще unsafe
подход, который возвращает обратную копию строки (без махинаций с обращением на месте) значительно быстрее, чем Array.Reverse
метод для небольших строк:
public static unsafe string Reverse(string text)
{
int len = text.Length;
// Why allocate a char[] array on the heap when you won't use it
// outside of this method? Use the stack.
char* reversed = stackalloc char[len];
// Avoid bounds-checking performance penalties.
fixed (char* str = text)
{
int i = 0;
int j = i + len - 1;
while (i < len)
{
reversed[i++] = str[j--];
}
}
// Need to use this overload for the System.String constructor
// as providing just the char* pointer could result in garbage
// at the end of the string (no guarantee of null terminator).
return new string(reversed, 0, len);
}
Вот некоторые эталонные результаты.
Видно, что прирост производительности уменьшается, а затем исчезает по сравнению с методом Array.Reverse
по мере увеличения размера строк. Однако для строк малого и среднего размера этот метод трудно превзойти.
public string rev(string str)
{
if (str.Length <= 0)
return string.Empty;
else
return str[str.Length-1]+ rev(str.Substring(0,str.Length-1));
}