Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB6 > Overflow при MOD


Автор: gippa 12.5.2006, 20:26
Здравствуйте!

Подскажите, пожалуйста, кто знает - как избежать переполнения при выполнении A mod B, при условии, что A - double?

Пробовала заменить mod на:

C=int( A/B )
D=B*C
ostatok=A-D

Но результат равен нулю, хотя виндовский калькулятор выдает, что остаток равен 97. Может где точность вычислений подправить? И как это сделать?

PS надо посчитать --> 7^101 mod 239

Спасибо заранее : )
 

Автор: cardinal 13.5.2006, 02:29
Ради прикола начал разбираться с этим калькулятором (у которого нет функции ^)
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=64895&lngWId=1
Возведение в степень я уже реализовал. Осталось сделать Mod результата и если выйдет тоже 97, то считай проблема решена. Как сделаю выложу...

Главное преимущество этого калькулятора это использование ассемблера. smile  

Автор: gippa 13.5.2006, 09:16
Цитата

Ради прикола начал разбираться с этим калькулятором (у которого нет функции ^)
http://www.planet-source-code.com/vb/scrip...95&lngWId=1

Да-а... ну и навороченный же там калькулятор smile 

Автор: cardinal 13.5.2006, 16:17
Короче есть еще один калькулятор 

BigNumVB.zip, 72kB
http://home.versatel.nl/vspickelen/Largefiles/Download.htm

(не хуже вроде того, что я вчера нашел) и у него есть операция a^k по крайней мере.

Так вот написав такой код
Код

Option Explicit

Private Sub Form_Load()
Dim g As String, size As Long, sw As Integer
  sw = Init(size, g)
  Call Clear
  'XSw = 0
End Sub

Private Sub Command1_Click()
    Readst i(0), "7"
    Readst i(1), "101" '         pop operands
    
    Letf t2, 0
    Modpwr i(0), i(1), t2
    
    Readst i(1), "239" '         pop operands

    If Isf(i(1), 0) Then
        Data = " zero modulus"
        ErrSw = -1
    Else
        Moddiv i(0), i(1)
    End If

    If Not ErrSw Then
        'Slate.Stax 0: Slate.Drop 1
        Printn i(0), "", "", 0
    End If
    
    
    MsgBox Data
    
    Data = ""
End Sub

Private Sub Clear()
Dim t As Integer
  'Bar = 0
  ErrSw = 0
  Key = 0
  For t = 0 To 9
    i(t) = 1 + t: Letf i(t), 0
  Next t
  For t = 0 To 3
    St(t) = ""
  Next t
  'CLx = 0
  Lft = 0
'  InputN.Text = ""
End Sub

и воткнув в проект файлы Extension.bas, bignumVB.bi, PrintFun.bas и Supplement.bas и в папкус с проектом файл bignumVB.dll ты получишь нужный тебе результат.
То есть для того чтобы считать с большими числами (которые VB не поддерживает) тебе нужна спец. библиотека. 

Автор: gippa 13.5.2006, 17:14
Уххх... как-то все сложно получается, хотя вроде бы пустяковая операция.. smile
Спасибо большое за помощь  smile , буду разбираться! smile))  

Автор: Тутанхамец 13.5.2006, 20:45

Gippa, я запал на твой вопрос  smile 
И вот к чему это привело: 

Код

Dim a As Long
Dim a2 As Long
Dim a3 As Long
Dim a4 As Long
Dim a5 As Long
Dim a6 As Long
Dim a7 As Long
Dim a8 As Long

'7^101=20 множителей 7^5 и еще один множитель 7

a = 7 ^ 5 '
a2 = a Mod 239 'остаток от множителя 7^5. Таких остатков 20

a3 = a2 ^ 4 'возводим остаток в 4 степень, так что произведение двадцати a2 равно произведению пяти a3
 a4 = a3 Mod 239 'делим. Получаем следующий остаток - их уже всего пять. 

a5 = a4 ^ 2 'четыре из этих пяти преобразуме в два. Один из пяти пока остается. 
a6 = a5 Mod 239 'делим тот, которых два (не могу понятнее сказать!:))
a7 = a6 ^ 2 * a4 * 7 'остаток от деления возводим в квадрат (т.к. их два было) умножаем на тот из пяти, который остался и на 7 (которая 101-я степень)
a8 = a7 Mod 239 'и заключительный этап. 
MsgBox a8
'Заветное 97!!! (По крайней мере у меня результат совпал с калькуляторным)


ИТОГО: 

1) Диковатая штука, но зато без ассемблера и калькуляторов. 

2) Можно это свернуть в одну строку и обойтись без кучи переменных - я их для наглядности наплодил. 

3) Чтоб обрабатывать не только эти числа, а любые, можно написать функцию, наверное. Пусть кто хочет - займется. А может и у меня руки дойдут...

P.S. 

Если что не так... Я все-таки не математик. smile Но вроде результат совпадает.  

Автор: gippa 13.5.2006, 21:19
Цитата

Gippa, я запал на твой вопрос


Я рада, что вопрос такой "заводной" получился smile

А код действительно какой-то хитрый - мое понимание сломалось где-то на 19 строчке  smile 

Теперь по поводу самого задания. Формула в оригинале выглядит так: X(i+1)=7^X(i) mod 239, а 101 - это X(0). Так что навряд ли этот код можно будет и на все распространить... Тем более дальше (делала ручками на калькуляторе) там значения от единиц до сотен получаются.
Надо все-таки какую-нить универсалку сделать.

А вообще, спасибо за активное участие!  smile  

Автор: cardinal 13.5.2006, 21:48
Тутанхамец, подсказал мне одну мыслю. smile 

Врозможно это
Код

Option Explicit

Private Sub Command1_Click()
Dim Xi As Long
Dim X0 As Long
Dim k As Integer
Dim j As Integer
Dim i As Integer

i = 3

X0 = 101
For k = 1 To i
    Xi = 7
    For j = 1 To X0 - 1
        Xi = Xi * 7
        Xi = Xi Mod 239
    Next
    X0 = Xi
Next

MsgBox "X(" & i & ") = " & Xi
End Sub

тогда полное (и самое простое) решение задачи. До третьего элемента проверял на калькуляторе - вроде правильно. 

Автор: gippa 13.5.2006, 23:08
Ура, ура! Cardinal спасибо тебе большое! Действительно все с моими "ручными" ответами сходится! smile  smile  

Автор: gippa 16.5.2006, 22:11
Cardinal! Возник у меня еще один вопрос - чем ты руководствуешься, когда пишешь цикл 7-10 строчки:
Код

i = 3

X0 = 101
For k = 1 To i
    Xi = 7
    For j = 1 To X0 - 1
        Xi = Xi * 7
        Xi = Xi Mod 239
    Next
    X0 = Xi
Next


Как это можно обосновать? Т.е. может такое "правило" математическое есть? Почему это эквивалентно X(i+1)=7^X(i) mod 239?
Спасибо заранее за ответ smile 

Автор: cardinal 17.5.2006, 00:30
Посмотри, что Тутанхамец делает. Он предлагает возводить в степень (намного меньшую заданной), потом делать Mod, а потом возводить результат от Mod'a дальше в степень. На числах можно описать данное так.

Давай исходить от простого 7^5 mod 10. То есть цикл крутиться четыре раза. Смотрим что получается.
Код

xi = xi * 7 = 7 * 7 = 49
xi = xi mod 10 = 49 mod 10 = 9

xi = xi * 7 = 9 * 7 = 63
xi = xi mod 10 = 63 mod 10 = 3

xi = xi * 7 = 3 * 7 = 21
xi = xi mod 10 = 21 mod 10 = 1

xi = xi * 7 = 1 *7 = 7
xi = xi mod 10 = 7 mod 10 = 7

Если посчитать тоже самое сразу 7^5 mod 10 то получится тот же ответ.

Получается, что 49 дает тот же остаток при делении на 10, что и число 9, так зачем нам 49, если можно взять 9 и ничего мы от этого не потеряем. Вся информация, которая нам нужна для Mod'a останется. 

Можно также привести такое правило (не знаю как его доказать на данный момент smile)
Код

(x*y) mod z = ((x mod z) * y) mod z
На примере
Код

(7*7) mod 5 = (7 mod 5) * 7) mod 5 = 4

При помощи этого правила я и сделал цикл. 

Автор: gippa 17.5.2006, 19:40
Cardinal еще раз шлю большие СПАСИБА smile) Все поняла, потому что очень доходчиво! smile smile  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)