Welcome to collectivesolver - Programming & Software Q&A with code examples. A website with trusted programming answers. All programs are tested and work.

Contact: aviboots(AT)netvision.net.il

Semrush - keyword research tool

Create your online store today with Shopify

Turn ChatGPT, Claude, Gemini, And CoPilot Into Your Personal Assistant, Business Coach, Content Creator, And More

AFFILIATE MARKETING Your all-in-one performance engine Manage affiliates, creators, and customer referrals in one unified platform—turning every partnership into measurable growth

Secure & Reliable Web Hosting, Free Domain, Free SSL, 1-Click WordPress Install, Expert 24/7 Support

Disclosure: My content contains affiliate links.

43,406 questions

56,397 answers

573 users

How to convert a decimal number to a rational number in Go

1 Answer

0 votes
package main

import (
    "fmt"
    "math/big"
    "strings"
)

/*
    convertDecimalToRational(s string)
    ----------------------------------
    Converts a decimal number (given as a string) into an exact rational p/q.

    Why parse the string manually?
        • Go has no built‑in rational type.
        • float64 cannot preserve exact decimal digits.
        • Using strings + big.Int ensures perfect accuracy.

    Algorithm:
        1. Look for a decimal point.
        2. If none → integer → numerator = n, denominator = 1.
        3. Otherwise:
              Example: "12.345"
              integer part   = 12
              fractional part = 345
              digits = 3

              numerator   = integer_part * 10^digits + fractional_part
              denominator = 10^digits

        4. Reduce using gcd (Euclid’s algorithm).
*/

// gcd computes the greatest common divisor using Euclid’s algorithm.
func gcd(a, b *big.Int) *big.Int {
    zero := big.NewInt(0)
    tmp := new(big.Int)

    for b.Cmp(zero) != 0 {
        tmp.Set(b)
        b.Mod(a, b)
        a.Set(tmp)
    }
    if a.Sign() < 0 {
        a.Neg(a)
    }
    return a
}

// convertDecimalToRational converts a decimal string into numerator/denominator.
func convertDecimalToRational(s string) (*big.Int, *big.Int) {
    dotPos := strings.Index(s, ".")
    if dotPos == -1 {
        // No decimal point → integer
        n := new(big.Int)
        n.SetString(s, 10)
        return n, big.NewInt(1)
    }

    intPart := s[:dotPos]
    fracPart := s[dotPos+1:]

    integerValue := new(big.Int)
    integerValue.SetString(intPart, 10)

    fractionalValue := new(big.Int)
    fractionalValue.SetString(fracPart, 10)

    digits := len(fracPart)

    // denominator = 10^digits
    denominator := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(digits)), nil)

    // numerator = integerValue * denominator + fractionalValue
    numerator := new(big.Int).Mul(integerValue, denominator)
    numerator.Add(numerator, fractionalValue)

    // Reduce fraction
    g := gcd(new(big.Int).Set(numerator), new(big.Int).Set(denominator))
    numerator.Div(numerator, g)
    denominator.Div(denominator, g)

    return numerator, denominator
}

func main() {
    values := []string{
        "3.5", "12.75", "0.125", "100.001",
        "7", "42.0", "0.333", "5.2",
    }

    for _, v := range values {
        num, den := convertDecimalToRational(v)
        fmt.Printf("%s -> %s/%s\n", v, num.String(), den.String())
    }
}



/*
run:

3.5 -> 7/2
12.75 -> 51/4
0.125 -> 1/8
100.001 -> 100001/1000
7 -> 7/1
42.0 -> 42/1
0.333 -> 333/1000
5.2 -> 26/5

*/

 



answered Jul 23 by avibootz

Related questions

...