Comparar números racionales

12

Dados a,b,c,dN y b,d{0} ,

ab<cdad<cb

Mis preguntas son:

Dado a,b,c,d

  1. Suponiendo que podemos decidir x<yZ en O(|x|+|y|) , ¿hay alguna forma de decidir ad<cb sin tener que preformar las multiplicaciones (o divisiones), ad y cb . ¿O hay algún tipo de prueba de que no hay manera?
  2. ¿Existe un método más rápido para comparar números racionales que multiplicar los denominadores?
Ensalada Realz
fuente
1
@PKG pero la multiplicación tomará más que tiempo lineal. Creo que queremos algo más rápido para esta pregunta.
Joe
1
El caso complicado es cuando un intervalo contiene otro, por ejemplo, [a,d][b,c] .
PKG
1
Usted suponen implícitamente que y d tiene el mismo signo. De lo contrario, la dirección de la desigualdad cambia. bd
Ran G.
1
(1) La multiplicación es casi lineal (busque el algoritmo de Fürer). (2) Un "número entero racional", al menos en el contexto de la teoría algebraica de números, en realidad solo significa un número entero. Quiere decir "racional" o "número racional".
Yuval Filmus
1
ver también duplicado aparente ¿Cómo comparar números racionales?
vzn

Respuestas:

5

Mi investigación actual:

Intento inicial de algunas reglas generales

Uno puede tratar de hacer algunas reglas generales para resolver la comparación racional:

Asumiendo todos los positivos :a,b,c,d

a<bcdab<cd
Básicamente, esto significa que si el lado izquierdo es menor que uno y el lado derecho es al menos uno, el lado izquierdo es menor que el derecho. En la misma vena:

abcdabcd

Otra regla:

(b>d)(ac)[ab<cd]
Creo que esta regla es lógica, ya que cuanto mayor es el denominador, menor es el número, mientras mayor el numerador, cuanto mayor sea el número. Por lo tanto, si el lado izquierdo tiene un denominador mayor y un numerador más pequeño, el izquierdo será más pequeño.

De ahora en adelante, asumiremos que , porque de lo contrario podemos resolverlo con las reglas anteriores o revertir la pregunta a , y terminamos con esta condición de todos modos.ca<cb<dcd<?ab

Reglas : Esto La regla básicamente establece que siempre se pueden restar los numeradores de los denominadores y establecer los resultados como numeradores para obtener un problema equivalente. Dejaré fuera la prueba.

(ba)b<(dc)d[ab<cd]|a<c,b<d

ab<cadb[ab<cd]|a<c,b<d

Esta regla le permite restar el numerador y el denominador izquierdos del numerador y el denominador correctos para un problema equivalente.

Y, por supuesto, hay escala:

akbk<cd[ab<cd]|a<c,b<d
You puede usar la escala para hacer que las reglas de resta anteriores sean más significativas.

Usando estas reglas puedes jugar con cosas, aplicarlas repetidamente, en combinaciones inteligentes, pero hay casos en que los números son cercanos y patológicos.

Al aplicar las reglas anteriores, puede reducir todos estos problemas a:

ab<ap+qbp+qab<qq|a>q,b>q

A veces puedes resolver esto directamente ahora, a veces no. Los casos patológicos suelen tener la forma:

ab<cd|a>c,b>d,cO(a),dO(b)

Luego lo voltea y da como resultado lo mismo, solo que con un poco menos. Cada aplicación de las reglas + volteo lo reduce en un dígito / bit. AFAICT, no puede resolverlo rápidamente, a menos que aplique las reglas veces (una vez por cada dígito / bit) en el caso patológico, negando su aparente ventaja.O(n)

¿Problema abierto?

Me di cuenta de que este problema parece ser más difícil que algunos problemas abiertos actuales.

Un problema aún más débil es determinar:

ad=?bc

Y aún más débil:

ad=?c

Este es el problema abierto de verificar la multiplicación . Es más débil, porque si tuviera una manera de determinar , ¿entonces puede determinar fácilmente el , al probar usando el algoritmo dos veces, , . Iff tampoco es cierto, ya sabes que .ad<?bcad=?bcad<?bcbc<?adadbc

Ahora, ¿ era un problema abierto, al menos en 1986:ad=?c

La complejidad de la multiplicación y división. Comencemos con la ecuación muy simple ax = b. Cuando se considera sobre los enteros, es posible probar su capacidad de solución y encontrar una solución x mediante la división de enteros con el resto cero. Para verificar una solución dada x, la multiplicación de enteros será suficiente, pero es un problema abierto interesante si existen métodos de verificación más rápidos.

- ARNOLD SCHÖNHAGE en resolución de ecuaciones en términos de complejidad computacional

Muy interesante, también mencionó la cuestión de verificar la multiplicación de matrices :

También es una pregunta interesante si la verificación de la multiplicación de matrices, es decir, verificar si AB = G para un C dado, podría hacerse más rápido.

- ARNOLD SCHÖNHAGE en resolución de ecuaciones en términos de complejidad computacional

Esto se ha resuelto desde entonces, y de hecho es posible verificar en tiempo con un algoritmo aleatorio (con siendo el tamaño de las matrices de entrada, por lo que es básicamente un tiempo lineal en el tamaño de la entrada). Me pregunto si es posible reducir la multiplicación de enteros a la multiplicación de matrices, especialmente con sus similitudes, dadas las similitudes de la multiplicación de enteros de Karatsuba con los algoritmos de multiplicación de matrices que siguieron. Entonces, tal vez de alguna manera podamos aprovechar el algoritmo de verificación de multiplicación de matrices para la multiplicación de enteros.O(n2)n×n

De todos modos, dado que esto sigue siendo, que yo sepa, un problema abierto, ¿el problema más fuerte de seguramente está abierto. Tengo curiosidad por saber si resolver el problema de verificación de igualdad tendría alguna relación con el problema de verificación de desigualdad de comparación.ad<?cd

Una ligera variación de nuestro problema sería si se garantiza que las fracciones se reduzcan a los términos más bajos; en este caso es fácil saber si . ¿Puede esto tener alguna relación con la verificación de comparación para fracciones reducidas?ab=?cd

Una pregunta aún más sutil, ¿y si tuviéramos una forma de probar , ¿esto se extendería a probar ? ¿No veo cómo puede usar estas "dos formas" como lo hicimos para .ad<?cad=?cad<?cd

Relacionado:

  • Reconocimiento aproximado de idiomas no regulares por autómatas finitos

    Trabajan un poco en la multiplicación aproximada y la verificación aleatoria, que no entiendo completamente.

  • mates.SE: ¿Cómo comparar dos multiplicaciones sin multiplicar?
  • Supongamos que se nos permite preprocesar tanto como quisiéramos en tiempo polinómico, ¿podemos resolver en tiempo lineal?cab=c
  • ¿Existe un algoritmo de multiplicación de enteros no determinista de tiempo lineal? Ver http://compgroups.net/comp.theory/nondeterministic-linear-time-multiplication/1129399

    Existen algoritmos bien conocidos para multiplicar números de n bits con algo como la complejidad O (n log (n) log (log (n))). Y no podemos hacerlo mejor que O (n) porque al menos tenemos que mirar las entradas completas. Mi pregunta es: ¿podemos realmente llegar a O (n) para una clase adecuada de algoritmos "no deterministas"?

    Más precisamente, ¿hay un algoritmo que pueda aceptar dos números binarios de n bits "a" y "b" y un número de 2 n bits "c" y decirle en O (n) tiempo si "a * b = c"? Si no es así, ¿existe alguna otra forma de certificado C (a, b, c) de manera que un algoritmo pueda usarlo para probar el producto en tiempo lineal? Si no es el tiempo lineal, ¿es el problema de probar el producto al menos asintóticamente más fácil que calcularlo? Cualquier resultado conocido en este sentido sería bienvenido.

    John.

    ―Johnh4717

Ensalada Realz
fuente
1

Aquí hay un intento muy parcial de refutar. Supongamos que podemos usar solo un (número constante de) sumas y restas en nuestro decisor, así como un número constante de números predefinidos wrt. En otras palabras, podemos hacer un número constante de , , etc. en nuestro decisor. Entonces, las únicas cantidades que podemos calcular son de la forma donde las son constantes predefinidas. Tenga en cuenta que puede calcularse en el tiempo .modmod 2mod 3q=k1a+k2b+k3c+k4d=kiakqO(|a|)

Editado Este decisor pretende determinar un bit iff . Considere tomar como puntos en . El bit se decide por su posición en la superficie que es un hiperboloide en 4 dimensiones. Si tenemos un punto en el espacio de entrada, el decisor anterior puede calcular puntos dentro de una distancia acotada de este punto de entrada, es decir, esos puntos etc. Esto define un cuboide en 4 d espacio.a d > b c a , b , c , d R 4 B a d = b c ( a , b , c , d ) q : | q - a | =B:B=1ad>bca,b,c,dR4Bad=bc(a,b,c,d)q:|qa|=k1,

(¿Cómo hacer que esto sea más preciso?) La distancia desde el cuboide hasta la superficie es generalmente ilimitada y, por lo tanto, la superficie no puede ser calculada por el decisor

PKG
fuente
Lo siento, no respondí a esto. Creo que esto podría estar simplemente por encima de mi comprensión, y mientras tanto he estado ocupado investigando posibles respuestas.
Realz Slaw
1

Buena pregunta. ¿Aceptarías un nivel de confianza?

Quizás hacer una división aproximada. Es decir

Para calcular los cocientes aproximados delimitadores de a / b, desplace a la derecha a por ceil (log_2 (b)) y también por floor (log_2 (b)). Entonces sabemos que el cociente exacto se encuentra entre estos dos valores.

Luego, dependiendo de los tamaños relativos de los cuatro enteros, uno puede descartar ciertos casos y obtener el 100% de confianza.

Uno puede repetir el procedimiento para radix que no sea 2, y mediante una sucesión de tales operaciones aumentar el nivel de confianza, hasta que se observe de alguna manera un cambio de signo / desempate.

Ese es mi primer borrador de un método.

Cris Stringfellow
fuente
Si miras mi respuesta de "investigación actual", creo que esas reglas hacen algo en este sentido. Puede continuar, muchas veces obteniendo un 100% de confianza si cumple con una de las primeras reglas, y en el peor de los casos, sigue repitiendo las últimas reglas una y otra vez eliminando un poco cada ronda, de manera similar a lo que sugiere, creo. Sin embargo, mi pregunta es sobre algo definitivo en (o mejor dicho, mejor que la multiplicación, también satisfaría esta pregunta), o al menos un algoritmo aleatorio con alguna probabilidad exponencialmente pequeña de fracaso O ( n log n )O(n)O(nlogn)
Realz Slaw
Además, si se pudiera verificar que este es un problema abierto, y no de alguna manera inherentemente más difícil que verificar (ver mi respuesta de "investigación actual", sección ¿ Problema abierto? ), O si hay alguna otra investigación o resultados interesantes existentes sobre esto, entonces eso también podría ser una respuesta aceptable. ab=c
Realz Slaw
1

¿Hay alguna forma de decidir ad <cb sin tener que preformar las multiplicaciones [caras]

Seguro.

Idea: Compara la expansión decimal bit por bit.

Lo único desagradable es que primero tenemos que excluir la igualdad porque de lo contrario no podremos terminar.
Es útil comparar primero las partes enteras porque eso es fácil.

Considera esto:

def less( (a,b), (c,d) ) = {
  // Compare integer parts first
  intA = a div b
  intC = c div d

  if intA < intB
    return True
  else if intA > intB
    return False
  else // intA == intB
    // Normalize to a number in [0,1]
    a = a mod b
    c = c mod d

    // Check for equality by reducing both
    // fractions to lowest terms
    (a,b) = lowestTerms(a,b)
    (c,d) = lowestTerms(c,d)

    if a == c and b == d
      return False
    else
      do
        // Compute next digits in decimal fraction 
        a = 10 * a
        c = 10 * c

        intA = a div b
        intC = c div d

        // Remove integer part again
        a = a mod b
        c = c mod d
      while intA == intC

      return intA < intC
    end
  end
}

Tenga en cuenta que el do-whileciclo tiene que terminar ya que los números son desiguales. Sin embargo, no sabemos cuánto tiempo dura; Si los números están muy cerca, podría pasar un tiempo.

Claramente, no hay multiplicaciones costosas; lo único que necesitamos es multiplicar los nominadores por . En particular, hemos evitado computar y explícitamente.a d c b10adcb

¿Esto es rápido? Probablemente no. Hay muchas divisiones enteras, módulos ys gdcpara calcular, y tenemos un ciclo cuyo número de iteraciones es inversamente proporcional a la distancia entre los números que comparamos.


El método auxiliar:

def lowestTerms(a,b) = {
  d = gcd(a,b)
  if d == 1
    return (a,b)
  else
    return lowestTerms(a div d, b div d)
  end
}
Rafael
fuente
a/bc/dadbcadcb
@DavidRicherby Hm. Estaba pensando principalmente en los desbordamientos: aquí, es menos probable que las operaciones creen grandes cantidades.
Raphael