gacar Ответов: 5

Преобразовать любую базу типа BigInteger на базе 10 и снова преобразовать обратно базу


Я хочу преобразовать значение biginteger базы 3 в базу 10 и снова преобразовать базу 3. Как я могу это сделать?

Я использую этот код для этого. Но я получаю неверный результат. Этот код работает для коротких значений, например("22222222210222211011111222")

Что я уже пробовал:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim BigValue As BigInteger = BigInteger.Parse("22222222210222211011111222011100022001111")
    Dim TenBase As BigInteger = ToTenBase(BigValue, 3)
    Dim TenBaseByte As Byte() = TenBase.ToByteArray
    Dim TreeBase As String = FromTenBase(TenBase, 3)
    If BigValue.ToString <> TreeBase.ToString Then Stop 'Stopping here
End Sub

Function ToTenBase(ByVal BigValue As BigInteger, ByVal Base As BigInteger) As String
    Dim Result As BigInteger = 0
    Dim strValue = BigValue.ToString.ToCharArray
    For i As BigInteger = strValue.Count - 1 To 0 Step -1
        Dim d As BigInteger = strValue(i).ToString
        Dim counter As BigInteger = ((strValue.Count - 1) - i)
        Result = Result + d * (BigInteger.Pow(Base, counter))
    Next
    Return Result.ToString
End Function

Function FromTenBase(BigValue As BigInteger, Base As BigInteger) As String
    Dim Result As String = ""
    Dim Division As BigInteger = BigValue
    Dim Remaining As BigInteger
    Dim Dividing As BigInteger

    Do Until Division < Base
        Dividing = Division
        Division = BigInteger.Divide(Division, Base)
        Remaining = Dividing - Division * Base
        Result = Remaining.ToString & Result
    Loop
    Result = Division.ToString & Result
    Return BigInteger.Parse(Result).ToString
End Function

Kornfeld Eliyahu Peter

Это может подойти вам: https://www.codeproject.com/Tips/1085580/On-What-Base-Do-You-Stand

CPallini

Мои виртуальные 5 (а также фактические 5 на ваш совет).

Kornfeld Eliyahu Peter

Спасибо...

5 Ответов

Рейтинг:
9

gacar

Преобразованный Кеннет Хогленд's решение проблемы vb.net ибо vb.net пользователи.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim input As String = "222222222102222110111112220111000220011110000011112222101111222011"
    Dim Base As String = "012"
    Dim base10number As BigInteger = ToBase10Horner(input, Base)
    Dim output = FromBase10(base10number, Base)
    Dim IsTheSameNumber = input.Equals(output.ToString())
End Sub

Private Shared Function FromBase10(value As BigInteger, BaseChars As String) As String
    Dim sign As Integer = 1
    If value < 0 Then
        sign = -1
    ElseIf value = 0 Then
        Return BaseChars.ToCharArray()(0).ToString()
    End If
    value *= sign

    Dim Result As New StringBuilder()
    Dim nBase As Integer = BaseChars.Length
    Dim Reminder As BigInteger = value

    Do
        Dim ModnBase As BigInteger = (Reminder Mod nBase)
        Result.Append(BaseChars.ToCharArray()(ModnBase))
        Reminder /= nBase
    Loop While Reminder <> 0
    If sign = -1 Then
        Result.Append("-"c)
    End If

    Dim charArray As Char() = Result.ToString().ToCharArray()
    Array.Reverse(charArray)
    Return New String(charArray)
End Function

Private Shared Function ToBase10Horner(Value As String, BaseChars As String) As BigInteger
    Dim nBase As BigInteger = BaseChars.Length
    Dim count As Integer = Value.Length - 1
    Dim nResult As BigInteger = 0

    Dim i As Integer = 0
    While i < count
        Dim bi As BigInteger = BaseChars.ToUpper().IndexOf(Value.ToCharArray()(i))
        nResult = nBase * (nResult + bi)
        System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
    End While
    Dim co As BigInteger = BaseChars.ToUpper().IndexOf(Value.ToCharArray()(count))
    nResult += co

    Return (nResult)
End Function


Рейтинг:
25

Kenneth Haugland

Вы слышали об этом Метод Хорнера[^Это может устранить необходимость брать силу чисел, а вы обычно не хотите этого делать, так как это очень медленно.

Код вызова и проверки таков:

string input = "22222222210222211011111222011100022001111";
string Base = "012";
BigInteger base10number = ToBase10Horner(input, Base);
var output = FromBase10(base10number, Base);
var IsTheSameNumber = input.Equals(output.ToString());
То, что я сделал, было следующим кодом:
static string FromBase10(BigInteger value, string BaseChars)
{
    int sign = 1;
    if (value < 0)
    {
        sign = -1;
    }
    else if (value == 0)
    {
        return BaseChars.ToCharArray()[0].ToString();
    }
    value *= sign;

    StringBuilder Result = new StringBuilder();
    int nBase = BaseChars.Length;
    BigInteger Reminder = value;

    do
    {
        BigInteger ModnBase = (Reminder % nBase);
        Result.Append(BaseChars.ToCharArray()[(int)ModnBase]);
        Reminder /= nBase;
    } while (Reminder != 0);
    if (sign == -1)
        Result.Append('-');

    char[] charArray = Result.ToString().ToCharArray();
    Array.Reverse(charArray);
    return new string(charArray);
}

static BigInteger ToBase10Horner(string Value, string BaseChars)
{
    BigInteger nBase = BaseChars.Length;
    int count = Value.Length - 1;
    BigInteger nResult = 0;

    for (int i = 0; i < count; i++)
    {
        nResult = nBase * (nResult + (BigInteger)BaseChars.ToUpper().IndexOf(Value.ToCharArray()[i]));
    }

    nResult += (BigInteger)BaseChars.ToUpper().IndexOf(Value.ToCharArray()[count]);

    return (nResult);
}


gacar

Спасибо за решение. Нет, я не слышал этого метода раньше. Но я попробовал этот метод и снова получил ошибку. Этот метод работает с короткими значениями biginteger, но получает ошибку с длинными значениями.

Kenneth Haugland

Я заставил его работать для всех случаев в C#. Он отлично возвращает входные данные.

gacar

Вы снова проверяли значения, чтобы вернуться на базу? Если тогда вы можете поделиться методом "десять оснований для другого", пожалуйста.

gacar

Да, действительно работает под vb.net сейчас же. Спасибо за решение. Я дал 5 звезд и принял решение. Потому что я вычисляю elepsed times between, ваше решение elepsed "0" milisecond :) , мое решение elepsed "1" milisecond . Действительно очень быстро.

Kenneth Haugland

Вы должны смотреть на Тики, а не на миллисекунды. Я обнаружил, что способ Horners был примерно вдвое быстрее, чем методы военнопленных.

Рейтинг:
2

OriginalGriff

Почему вы используете струны? Это очень расточительно и неэффективно.
Вместо этого используйте операции BigInteger Divide и Modulus для извлечения каждой цифры по одной за раз и включения ее в текущий итог:

set powerOf = 1
set total = 0
while input not zero
   extract lowest digit using modulus 10
   multiply digit by powerOf
   add to total
   multiply powerOf by base
   divide input by 10


CPallini

Почему вы используете струны? Это очень расточительно и неэффективно.
ОП должен это сделать (если только я чего-то не упустил). Я имею в виду, что должны быть предоставлены как "parseFromBase3String", так и "FormatToBase3String" (поскольку BigIteger их не предоставляет).

Рейтинг:
2

Patrice T

Ваш код представляет собой беспорядок каскадных преобразований, вам нужно проверить, что каждое преобразование работает должным образом, используйте для этого отладчик.
BigValue и TenBase есть BigInteger, и вы хотите
TenBase = ToTenBase(BigValue, 3)
смотрите, что Вы делаете с ToTenBase
ToTenBase не BigValue как BigInteger =&ГТ; метод toString =&ГТ; ToCharArray =&ГТ; метод toString =&ГТ; ToBigInteger =&ГТ; метод toString =&ГТ; ToBigInteger
совет: у вас есть BigInteger, вы хотите BigInteger, оставайтесь BigInteger.
-----
Существует довольно простой способ извлечения цифр из числа без преобразования в строку
Би = 22222222210222211011111222011100022001111
Un = BI % 10 = 1
Tn = BI / 10 = 2222222221022221101111122201110002200111
повторите операцию для каждой цифры, которая вам нужна.
-----
Существует инструмент, который позволяет вам видеть, что делает ваш код, его имя отладчик Это также отличный инструмент обучения, потому что он показывает вам реальность, и вы можете увидеть, какие ожидания соответствуют реальности.
Когда вы не понимаете, что делает ваш код или почему он делает то, что он делает, ответ таков: отладчик.
Используйте отладчик, чтобы увидеть, что делает ваш код. Просто установите точку останова и посмотрите, как работает ваш код, отладчик позволит вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения.

Отладчик - Википедия, свободная энциклопедия[^]
Visual Basic / Visual Studio Video Tutorial - Базовая Отладка - YouTube[^]
Visual Basic .NET programming for Beginners - точки останова и средства отладки[^]
Отладчик здесь, чтобы показать вам, что делает ваш код, и ваша задача-сравнить с тем, что он должен делать.
В отладчике нет никакой магии, он не находит ошибок, он просто помогает вам. Когда код не делает того, что ожидается, вы близки к ошибке.


Рейтинг:
16

gacar

Я нашел это решение и сейчас работаю. Благодаря Корнфельд Элиягу Петер для взносов. ( На-Каком-Основании-Ты-Стоишь)

 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
     Dim BigValue As BigInteger = BigInteger.Parse("22222222210222211011111222011100022001111")
     Dim TenBase As BigInteger = ToTenBase(BigValue, 3)
     Dim TenBaseByte As Byte() = BigValue.ToByteArray
     Dim TreeBase As BigInteger = FromTenBase(TenBase, 3)
     If BigValue.ToString <> TreeBase.ToString Then Stop
 End Sub

Function ToTenBase(ByVal BigValue As BigInteger, ByVal Base As Integer) As BigInteger
     Dim Total As BigInteger
     Dim str As String = BigValue.ToString
     str = StrReverse(str)
     For i As Integer = str.Length - 1 To 0 Step -1
         Dim k As Integer = Microsoft.VisualBasic.Val(str(i))
         Total = Total + k * (Base) ^ i
     Next
     Return Total
 End Function

 Function FromTenBase(BigValue As BigInteger, Base As Integer) As BigInteger
     Dim BigByte() As Byte = BigValue.ToByteArray
     Dim Remaining As Numerics.BigInteger = BigValue
     Dim Count As Integer = Fix(Math.Log(BigValue, Base))
     Dim Result(Count) As Byte
     Do Until Remaining <= 0
         Dim Pow As Integer = Fix(Math.Log(Remaining, Base))
         Dim Division As BigInteger = Remaining / Base ^ Pow
         Result(Pow) = Division
         Remaining = Remaining - (Division* Base ^ Pow)
     Loop
     Array.Reverse(Result)
     Return BigInteger.Parse(ArrayToString(Result))
 End Function

 Function ArrayToString(ByVal Arr As Array) As String
     Dim s As String
     For i As Integer = 0 To Arr.Length - 1
         s = s & Arr(i)
     Next
     Return s
 End Function