Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 |

 

  Вопрос: Помогите с C# Добавлено: 14.01.12 01:38  

Автор вопроса:  Ahtoxa

Ответить

  Ответы Всего ответов: 29  

Номер ответа: 16
Автор ответа:
 VbStarter



ICQ: 357911808 

Вопросов: 118
Ответов: 1340
 Web-сайт: moscowdevils.ru
 Профиль | | #16
Добавлено: 14.01.12 22:50
а на
  1. a = (a + CType((url((k + 0))  _
  2.             + ((url((k + 1)) + 8)  _
  3.             + ((url((k + 2)) + 16)  _
  4.             + (url((k + 3)) + 24)))),UInteger))

Ответить

Номер ответа: 17
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #17
Добавлено: 14.01.12 22:56
VbStarter, твой второй вариант - фейл. Там не плюс, а сдвиг должен быть.
Ahtoxa, еще раз повторю. url(k + 1) - это Char, т.е. 2байтный юникодный символ, операция сдвига для символов не определена. Отсюда и ошибка, что сдвиг не определён для Char и Integer (8, 16, 24). Надо перед сдвигом конвертировать символ в число с помощью Convert.ToUInt32, а не пытаться конвертировать результат.
Но вот откуда оверфлоу не понятно. Мне кажется прибавляется дофига большое число к a. Пробуй присвоить a изначально 0, или использовать везде UInt64 (и ToUInt32), разделить строку на несколько строк, чтобы более конкретно понять, где происходит переполнение

Ответить

Номер ответа: 18
Автор ответа:
 VbStarter



ICQ: 357911808 

Вопросов: 118
Ответов: 1340
 Web-сайт: moscowdevils.ru
 Профиль | | #18
Добавлено: 14.01.12 22:57
посмотри здесь
http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/f7faf3e1-f9a2-4370-b1d6-e0fc9311f176

Ответить

Номер ответа: 19
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #19
Добавлено: 14.01.12 22:58
читать как ";(и ToUInt64)" естественно:)

Ответить

Номер ответа: 20
Автор ответа:
 Ahtoxa



Вопросов: 6
Ответов: 29
 Профиль | | #20 Добавлено: 14.01.12 23:04
Действительно, Winand. Спасибо
  1.   Dim url As String
  2.         Dim k As Integer
  3.         Dim a As UInteger
  4.         url = "Hello"
  5.         k = 1
  6.         a = 1
  7.         a += Convert.ToUInt32(url(k + 0)) + (Convert.ToUInt32(url(k + 1)) << 8) + (Convert.ToUInt32(url(k + 2)) << 16) + (Convert.ToUInt32(url(k + 3)) << 24)
  8.         MsgBox(a)

Так никакой ошибки.

Как-то так нужно:
  1.    Dim url As String
  2.         Dim k As Integer
  3.         Dim a As ULong
  4.         url = "Hello"
  5.         k = 1
  6.         a = 2654435769
  7.         a += Convert.ToUInt32(url(k + 0)) + (Convert.ToUInt32(url(k + 1)) << 8) + (Convert.ToUInt32(url(k + 2)) << 16) + (Convert.ToUInt32(url(k + 3)) << 24)
  8.         MsgBox(a)

Ответить

Номер ответа: 21
Автор ответа:
 Ahtoxa



Вопросов: 6
Ответов: 29
 Профиль | | #21 Добавлено: 14.01.12 23:50
Вот блин, снова :(
Уже теперь в функции Mix во второй строке "a = a - c" - Arithmetic operation resulted in an overflow.
a = 1 868 983 913, c = 3 862 272 612, т.е. должно получится отрицательное число, что недопустимо для ULong и UInteger.

Хотя в C# как-то работало, предполагаю что изначально в алгоритме предусматривалось что a, b, c - положительные, но у меня они неправильно рассчитались в функции GoogleChecksum.

Вот весь код:
  1. Private Shared Sub Mix(ByRef a As ULong, ByRef b As ULong, ByRef c As ULong)
  2.         a = a - b
  3.         a = a - c
  4.         a = a Xor c >> 13
  5.         b = (b - c)
  6.         b = (b - a)
  7.         b = b Xor a << 8
  8.         c = (c - a)
  9.         c = (c - b)
  10.         c = c Xor b >> 13
  11.         a = (a - b)
  12.         a = (a - c)
  13.         a = a Xor c >> 12
  14.         b = (b - c)
  15.         b = (b - a)
  16.         b = b Xor a << 16
  17.         c = (c - a)
  18.         c = (c - b)
  19.         c = c Xor b >> 5
  20.         a = (a - b)
  21.         a = (a - c)
  22.         a = a Xor c >> 3
  23.         b = (b - c)
  24.         b = (b - a)
  25.         b = b Xor a << 10
  26.         c = (c - a)
  27.         c = (c - b)
  28.         c = c Xor b >> 15
  29.     End Sub
  30.     Private Shared Function GoogleChecksum(ByVal url As String) As String
  31.         Dim GoogleMagic As UInteger = 3862272608
  32.         Dim b As ULong
  33.         Dim a As ULong
  34.         Dim c As ULong = GoogleMagic
  35.         b = 2654435769
  36.         a = 2654435769
  37.         Dim k As Integer = 0
  38.         Dim length As Integer = url.Length
  39.         While (length >= 12)
  40.             a += Convert.ToUInt32(url(k + 0)) + (Convert.ToUInt32(url(k + 1)) << 8) + (Convert.ToUInt32(url(k + 2)) << 16) + (Convert.ToUInt32(url(k + 3)) << 24)
  41.             b += Convert.ToUInt32(url(k + 4)) + (Convert.ToUInt32(url(k + 5)) << 8) + (Convert.ToUInt32(url(k + 6)) << 16) + (Convert.ToUInt32(url(k + 7)) << 24)
  42.             c += Convert.ToUInt32(url(k + 8)) + (Convert.ToUInt32(url(k + 9)) << 8) + (Convert.ToUInt32(url(k + 10)) << 16) + (Convert.ToUInt32(url(k + 11)) << 24)
  43.             Mix(a, b, c)
  44.             k = k + 12
  45.             length = length - 12
  46.         End While
  47.         c = c + CType(url.Length, ULong)
  48.         Select Case (length)
  49.             Case 11
  50.                 c += (Convert.ToUInt32(url(k + 10)) << 24)
  51.                 GoTo CaseLabel10
  52.             Case 10
  53. CaseLabel10:
  54.                 c += (Convert.ToUInt32(url(k + 9)) << 16)
  55.                 GoTo CaseLabel9
  56.             Case 9
  57. CaseLabel9:
  58.                 c += (Convert.ToUInt32(url(k + 8)) << 8)
  59.                 GoTo CaseLabel8
  60.             Case 8
  61. CaseLabel8:
  62.                 b += (Convert.ToUInt32(url(k + 7)) << 24)
  63.                 GoTo CaseLabel7
  64.             Case 7
  65. CaseLabel7:
  66.                 b += (Convert.ToUInt32(url(k + 6)) << 16)
  67.                 GoTo CaseLabel6
  68.             Case 6
  69. CaseLabel6:
  70.                 b += (Convert.ToUInt32(url(k + 5)) << 8)
  71.                 GoTo CaseLabel5
  72.             Case 5
  73. CaseLabel5:
  74.                 b += Convert.ToUInt32(url(k + 4))
  75.                 GoTo CaseLabel4
  76.             Case 4
  77. CaseLabel4:
  78.                 a += (Convert.ToUInt32(url(k + 3)) << 24)
  79.                 GoTo CaseLabel3
  80.             Case 3
  81. CaseLabel3:
  82.                 a += (Convert.ToUInt32(url(k + 2)) << 16)
  83.                 GoTo CaseLabel2
  84.             Case 2
  85. CaseLabel2:
  86.                 a += (Convert.ToUInt32(url(k + 1)) << 8)
  87.                 GoTo CaseLabel1
  88.             Case 1
  89. CaseLabel1:
  90.                 a += Convert.ToUInt32(url(k + 0))
  91.         End Select
  92.         Mix(a, b, c)
  93.         Return String.Format("6{0}", c)
  94.     End Function

Ответить

Номер ответа: 22
Автор ответа:
 Ahtoxa



Вопросов: 6
Ответов: 29
 Профиль | | #22 Добавлено: 15.01.12 01:26
Да, так и есть, не верно рассчитывались.

Запустил параллельно исходник на C# и на VB.NET
Всунул MessageBox в коде на C# в том же месте - получил такие же данные.
На VB.NET в цикле While после первого исполнения функции mix ругается на первую её строчку:
"a -= b" - Arithmetic operation resulted in an overflow.

  1.   Private Shared Function GoogleChecksum(ByVal url As String) As String
  2.         Dim GoogleMagic As UInteger = 3862272608
  3.         Dim b As ULong
  4.         Dim a As ULong
  5.         Dim c As ULong = GoogleMagic
  6.         b = 2654435769
  7.         a = 2654435769
  8.         Dim k As Integer = 0
  9.         Dim length As Integer = url.Length
  10.         Dim encoding As New System.Text.UTF8Encoding()
  11.         While (length >= 12)
  12.             a = CULng(a + CLng(BitConverter.ToUInt32(encoding.GetBytes(url), k) - 4294967296))
  13.             b = CULng(b + CLng(BitConverter.ToUInt32(encoding.GetBytes(url), k + 4) - 4294967296))
  14.             c = CULng(c + CLng(BitConverter.ToUInt32(encoding.GetBytes(url), k + 8) - 4294967296))
  15.             MsgBox(a & " " & b & " " & c)
  16.             Mix(a, b, c)

Ответить

Номер ответа: 23
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #23
Добавлено: 15.01.12 01:36
Вот как интересно работает C# http://ideone.com/Jnrsf А VB считает, что переполнение.

Ответить

Номер ответа: 24
Автор ответа:
 Ahtoxa



Вопросов: 6
Ответов: 29
 Профиль | | #24 Добавлено: 15.01.12 01:47
Ха... на C# тест:
  1. private static void Mix(ref uint a, ref uint b, ref uint c)
  2. {
  3.     MessageBox.Show(a.ToString() + " " + b.ToString());
  4.     a -= b;
  5.     MessageBox.Show(a.ToString() + " " + b.ToString());

Первый MessageBox: 228 452 386|229 040 371
Второй MessageBox: 4 294 379 311|229 040 371

a - b = 228 452 386-229 040 371 = - 587 985
Откуда такое a большое получилось? :)
4 294 379 311 может получится только так - верхняя граница Uint 4 294 967 295 - 587 985 + 1 = 4 294 379 311

Ответить

Номер ответа: 25
Автор ответа:
 Ahtoxa



Вопросов: 6
Ответов: 29
 Профиль | | #25 Добавлено: 15.01.12 01:56
Ещё один тест
C#:
  1.          uint a;
  2.          a = 10;
  3.          a -= 15;
  4.          MessageBox.Show(a.ToString());

4 294 967 291

VB.NET:
  1.         Dim a As UInteger = 10
  2.         a -= 15
  3.         MsgBox(a)

Arithmetic operation resulted in an overflow :)

Ответить

Номер ответа: 26
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #26
Добавлено: 15.01.12 02:00
Это то, о чём я написал выше. Вычитание происходит одинаково для знаковых и беззнаковых, а вот интерпретируются значения по-разному. Результатом здесь будет 1111 1111 1111 0111 0000 0111 0010 1111
В int это выглядит как -587.985, в uint - как 4.294.379.311
А бейсик видимо проверяет перед вычитанием, не получится ли результат выходящим за границы типа. И выдаёт ошибку.

Ответить

Номер ответа: 27
Автор ответа:
 Ahtoxa



Вопросов: 6
Ответов: 29
 Профиль | | #27 Добавлено: 15.01.12 02:08
Т.е. нужно вместо
a -= b
Сделать
If a >= b Then a -= b Else a = 4 294 967 296 + a - b

Ответить

Номер ответа: 28
Автор ответа:
 Winand



Вопросов: 87
Ответов: 2795
 Web-сайт: winandfx.narod.ru
 Профиль | | #28
Добавлено: 15.01.12 02:37
имхо, лучше a += 4294967295 - b + 1, так не вылезем за границы 4 байт.
Что удивительно здесь снова всё компилируется нормально:) http://ideone.com/teeH7

Ответить

Номер ответа: 29
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #29 Добавлено: 21.01.12 07:16
Операции сдвига переполнение не вызовут.

Не смотрел код, но из обсуждения полагаю, что переполнение происходит при присваивании отрицательного числа к беззнаковому типу.
В C# код работает, потому что там по умолчанию отключена проверка арифметических переполнений.
В VB .NET по умолчанию эта проверка включена, но ее можно отключить.

свойства проекта - вкладка Compile - Advanced compile options - опция Remove integer overflow checks (ее нужно активировать).

Побочный эфект состоит в том, что проверка отключится во всем проекте. Нет ключевого слова unchecked, как в C#, позволяющего отключить проверку переполнения локально. А проверку переполнений лучше иметь, так как почти во всех случаях при переполнении с отключенной проверкой мы получим мусор, который не предполагалось иметь, который вызывает некорректную работу программы - в таких случаях предпочтитетльнее ловить исключение.

другой вариант - делать присваивание через BitConverter - он позволяет копировать данные на бинарном уровне (т.е. как они представлены в памяти единицами и нулями)

  1.         Dim T1 As Int32 = -1
  2.         Dim buf As Byte() = BitConverter.GetBytes(T1)
  3.  
  4.         Dim T2 As UInt32 = BitConverter.ToUInt32(buf, 0)

Ответить

Страница: 1 | 2 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам