2016-04-11 22 views
2

içinde iki kat daha düşük olan iki sayıdan oluşan En Düşük Ortak Birden Çok Sayısını hesaplamamı isteyen bir Coursera sınıfı için bir ödev yapıyorum. Bunu yazıyorum C ve ben 226553150 ve 1023473145 numaraları ile bir test çantası üzerinde kodumu çalıştırıyorum. Cevap 46374212988031350, ama ben 6 tarafından kapalı olan 46374212988031344, alıyorum!En Düşük Ortak Çoklu C

Python'da, aşağıda yazdığımla esasen aynı yaklaşımı kullanan doğru bir çözüm yazdım, ancak sayısal kesinliğin ayrıntıları benim için açıktı. Ben C içinde yüzen nokta hassaslığı hakkında bir şey öğrenmek için SO göndermek ve LCM ile ilgili internette ve SO üzerinde gördüğüm çoğu soru sadece tamsayılarla anlaşma çünkü.

#include <stdio.h> 
#include <math.h> 

double gcd(double a, double b) { 
    if (b == 0) { 
     return a; 
    } 

    return gcd(b, fmod(a,b)); 
} 

double lcm(double a, double b) { 
    return (a * b)/gcd(a,b); 
} 

int main() { 

    double a; 
    double b; 

    scanf("%lf %lf", &a, &b); 

    printf("%.0lf\n", lcm(a,b)); 

    return 0; 
} 
+4

Bu tür görevlerde kayan nokta hesaplamalarını kullanmayın. Sadece tamsayı kullanın. Yüksek hassasiyete ihtiyacınız varsa uzun süre kullanın (veya uzun süre yeteri kadar büyük değilse keyfi doğruluk aritmetiği) – GMichael

+2

Bu formül '(a * b)/gcd (a, b)' 'çiftin tutabileceğinden daha fazla rakam ile sonuçlanacaktır. . Formülün nasıl geliştirileceğini düşünün ki bu olmayacak. –

+0

çiftinin yalnızca 15 haneli hassasiyeti vardır. 46374212988031350'yi tam olarak –

cevap

3

bir double ile temsil edilebilir 46374212988031350 en yakın numarası (2 olarak kapalı) 46374212988031352 olup. Bunu en düz ileri hesaplama kullanarak test edebilirsiniz.

#include <stdio.h> 

int main() { 

    // The gcd of 226553150 and 1023473145 is 5 
    double a = 226553150; 
    double b = 1023473145; 
    double c = b/5; 

    double lcm = a*c; 

    printf("lcm: %.0lf\n", lcm); 

    return 0; 
} 

Çıktı:

lcm: 46374212988031352 

Sen (a * b)/gcd(a, b) hesaplayarak kötü şeyler yapıyoruz. Kayan nokta sayılarıyla temsil edilebilen 231871064940156750, (a*b)'a en yakın sayı 231871064940156736'dur. Diğer bir deyişle, önce (a*b) hesaplanarak daha fazla doğruluk kaybedersiniz.

Aynı hesaplama için kullandığınız Python kodunu göndermediniz. Python'un sayılarla ilgili integral türleri kullandığını tahmin ediyorum. Ben kullanıyorsanız:

a = 226553150; 
b = 1023473145; 
c = b/5; 

lcm = a*c 

print("lcm:", lcm) 

Ben çıktı alın:

a = 226553150.0; 
b = 1023473145.0; 
c = b/5; 

lcm = a*c 

print("lcm:", "%18.0lf" % lcm) 

Çıktı: Ben a ve b için kayan noktalı sayıları sabit kullanırsanız, Ancak

('lcm:', 46374212988031350) 

, farklı bir çıktı almak :

('lcm:', ' 46374212988031352') 

Özetle, C programı ile Python programı arasında gördüğünüz fark, kayan nokta türlerinin integral türlerine göre kullanılmasından kaynaklanıyor. double yerine long veya long long kullanırsanız, the answer by Deng Haijun'da gösterildiği gibi Python programı ile aynı çıktıyı almalısınız.

1

değil uzun şamandıra kullanır neden şüphe: İşte

Ben gcc -pipe -O2 -std=c11 lcm.c ile derleme benim koddur. Şamandırayı takip ettiğim gibi değiştirdim, o zaman iyi çalışıyor.

#include <stdio.h> 
#include <math.h> 

long gcd(long a, long b) { 
    if (b == 0) { 
     return a; 
    } 

    return gcd(b, a%b); 
} 

long lcm(long a, long b) { 
    return (a * b)/gcd(a,b); 
} 

int main() { 

    long a; 
    long b; 

    scanf("%ld %ld", &a, &b); 
    printf("%ld\n", lcm(a,b)); 

    return 0; 
} 
+0

uzunluğunu 64 bit Windows'ta bile 32 bit depolayamaz.Önerilen yol 'int64_t' –

+0

@ LưuVĩnhPhúc Hayır, önerilen yol * x * y/z gibi şeyler yazmadan önce * düşünmenizdir *. –