在Google脚本上用分数求解数学方程式

时间:2018-09-23 19:33:51

标签: javascript math google-apps-script google-sheets

我正在制作一个Google表格程序来创建一个math worksheet,它会在某些参数内随机生成数字。

我成功地进行了加法,减法,加法和减法的混合以及乘法。我现在正在尝试将分数添加到混合中,但是遇到了格式问题。 虽然我已经能够生成随机分数并让它们正确显示,但是问题在于尝试在密钥表上生成正确的答案。

我试图找到一种方法来读取分数所占的单元格作为字符串并解析单个数字,但是这只会解决分子的问题,而我仍然遇到分母的问题(找到共同点或至少有一个答案,学生或老师在解决后可以简化答案。

我在上面包含了一个链接,如果您有任何想法可以解决此问题,请告诉我。

此外,由于我认为我没有在脚本中正确记录它,因此生成的整数的最大值位于关键页面上的“ K2”范围内

function myWSG() {
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var ws = ss.getSheetByName("Worksheet");
 var ks = ss.getSheetByName("Key");

 var m = ks.getRange('K2').getValue()+1;

 function getRandomInt(min, max) {
 min = Math.ceil(min);
 max = Math.floor(max);
 return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}
for (var i = 8; i <= 26; i = i + 2){
var num = getRandomInt(0, m);
var num1 = getRandomInt(0, m);
var dn1 = getRandomInt(0, m);
var dn2 = getRandomInt(0, m);
var sym = getRandomInt(0, 2);
ws.getRange("A1").copyFormatToRange(ws, 3, 3, i, i)
ws.getRange("A1").copyFormatToRange(ws, 5, 5, i, i)
 switch(ws.getRange(6, 5).getValue()){
  case "Fractions":
    ks.getRange("A6").setValue("Fractions");
    if(dn1 == 0){
      ws.getRange(i, 3).setValue(num)
    }
else if(dn1 == 1){
      ws.getRange(i, 3).setValue(num)
    }
    else{
      ws.getRange(i, 3).setValue(num + "/" + dn1);
    }
    if(dn2 == 0){
      ws.getRange(i, 5).setValue(num1)
    }
    else if(dn2 == 1){
      ws.getRange(i, 5).setValue(num1)
    }
    else{
      ws.getRange(i, 5).setValue(num1 + "/" + dn2);
    }
    break;
 case "Add&Sub":
    ks.getRange("A6").clearContent();
    if(num > num1){
      ws.getRange(i, 3).setValue(num);
      ws.getRange(i, 5).setValue(num1);
    }
    else{
      ws.getRange(i, 3).setValue(num1);
      ws.getRange(i, 5).setValue(num);
    }
    if(sym == 0){
      ws.getRange(i, 4).setValue('+')
     }
    else{
      ws.getRange(i, 4).setValue('-')
    }
    break;
  case "Addition":
    ks.getRange("A6").setValue("Fractions")
    ws.getRange(i, 4).setValue('+');
    if(num > num1){
      ws.getRange(i, 3).setValue(num);
      ws.getRange(i, 5).setValue(num1);
    }
    else{
      ws.getRange(i, 3).setValue(num1);
      ws.getRange(i, 5).setValue(num);
    }
    break;
  case "Subtraction":
    ks.getRange("A6").setValue("Fractions")
    ws.getRange(i, 4).setValue('-');
            if(num > num1){
      ws.getRange(i, 3).setValue(num);
      ws.getRange(i, 5).setValue(num1);
    }
    else{
      ws.getRange(i, 3).setValue(num1);
      ws.getRange(i, 5).setValue(num);
    }
    break;
  case "Multiplication":
    ks.getRange("A6").setValue("Fractions")
    ws.getRange(i, 4).setValue('x');
    ws.getRange(i, 3).setValue(num);
    ws.getRange(i, 5).setValue(num1);
    break;
 }
}
for (var v = 30; v <= 46; v = v + 3){
var vnum = getRandomInt(0, m); //random Integer 1
var vnum1 = getRandomInt(1, m); //random Integer 2
var vnum2 = getRandomInt(0, m); //random Integer 3
var vnum3 = getRandomInt(1, m); //random Integer 4
var vsym = getRandomInt(0, 2); //Symbol determinate
var vsym1 = getRandomInt(0, 2); //Symbol determinate 2
var vdn1 = getRandomInt(0, m); //random denominator 1
var vdn2 = getRandomInt(0, m); //random denominator 2
ws.getRange("A1").copyFormatToRange(ws, 3, 3, v, v); //Reset Format to 

ws.getRange("A1").copyFormatToRange(ws, 5, 5, v, v); //Reset Format to 

ws.getRange("N1").copyFormatToRange(ws, 3, 3, v+1, v+1); //Reset Format 

ws.getRange("N1").copyFormatToRange(ws, 5, 5, v+1, v+1); //Reset Format 

switch(ws.getRange(6, 5).getValue()){
  case "Fractions":
    if(vdn1 == 0){
      ws.getRange(v, 3).setValue(vnum);
    }
    else if(vdn1 == 1){
      ws.getRange(v, 3).setValue(vnum);
    }
    else{
      ws.getRange(v, 3).setValue(vnum + "/" + vdn1);
      ws.getRange(v, 5).setValue(vnum2 + "/" + vdn1);
    }
    if(vdn2 == 0){
      ws.getRange(v+1, 3).setValue(vnum1);
    }
    else if(vdn2 == 1){
      ws.getRange(v+1, 3).setValue(vnum1);
    }
    else{
      ws.getRange(v+1, 3).setValue(vnum1 + "/" + vdn2);
      ws.getRange(v+1, 5).setValue(vnum3 + "/" + vdn2);
    }
break;
  case "Add&Sub":
    if(vnum > vnum1){
      ws.getRange(v, 3).setValue(vnum);
      ws.getRange(v+1, 3).setValue(vnum1);
    }
    else{
      ws.getRange(v, 3).setValue(vnum1);
      ws.getRange(v+1, 3).setValue(vnum);
    }
    if(vnum2 > vnum3){
      ws.getRange(v, 5).setValue(vnum2);
      ws.getRange(v+1, 5).setValue(vnum3);
    }
    else{
      ws.getRange(v, 5).setValue(vnum3);
      ws.getRange(v+1, 5).setValue(vnum2);
    }
    if(vsym == 0){
      ws.getRange(v+1, 2).setValue('+');
    }
    else{
      ws.getRange(v+1, 2).setValue('-');
    }
    if(vsym1 == 0){
      ws.getRange(v+1, 4).setValue('-');
    }
    else{
      ws.getRange(v+1, 4).setValue('+');
    }
    break;
case "Addition":
    ws.getRange(v+1, 2).setValue('+');
    ws.getRange(v+1, 4).setValue('+');
    ws.getRange(v, 3).setValue(vnum);
    ws.getRange(v+1, 3).setValue(vnum1);
    ws.getRange(v, 5).setValue(vnum2);
    ws.getRange(v+1, 5).setValue(vnum3);
    break;
  case "Subtraction":
    ws.getRange(v+1, 2).setValue('-');
    ws.getRange(v+1, 4).setValue('-');
    if(vnum > vnum1){
      ws.getRange(v, 3).setValue(vnum);
      ws.getRange(v+1, 3).setValue(vnum1);
    }
    else{
      ws.getRange(v, 3).setValue(vnum1);
      ws.getRange(v+1, 3).setValue(vnum);
    }
    if(vnum2 > vnum3){
      ws.getRange(v, 5).setValue(vnum2);
      ws.getRange(v+1, 5).setValue(vnum3);
    }
    else{
      ws.getRange(v, 5).setValue(vnum3);
      ws.getRange(v+1, 5).setValue(vnum2);
    }
    break;
  case "Multiplication":
    ws.getRange(v+1, 2).setValue('x');
    ws.getRange(v+1, 4).setValue('x');
    ws.getRange(v, 3).setValue(vnum);
    ws.getRange(v+1, 3).setValue(vnum1);
    ws.getRange(v, 5).setValue(vnum2);
    ws.getRange(v+1, 5).setValue(vnum3);
    break;
  }
}
for ( var s = 8; s <= 26; s = s + 2){
  ks.getRange(s, 7).clearContent();
}
 for ( var s2 = 32; s2 <= 47; s2 = s2 + 3){
    ks.getRange(s2, 3).clearContent();
    ks.getRange(s2, 5).clearContent();
   }

}
function myKSG() {
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var ws = ss.getSheetByName("Worksheet");
 var ks = ss.getSheetByName("Key");

 for ( var s = 8; s <= 26; s = s + 2){
   var nm = ks.getRange(s, 3).getValue();
   var nm1 = ks.getRange(s, 5).getValue();

   switch(ws.getRange(s, 4).getValue()){
    case "+":
      ws.getRange(s, 4).copyFormatToRange(ks, 7, 7, s, s);
      ks.getRange(s, 7).setValue(nm + nm1);
      break;
    case "-":
      ws.getRange(s, 4).copyFormatToRange(ks, 7, 7, s, s);
      ks.getRange(s, 7).setValue(nm - nm1);
    break;
    case "x":
      ws.getRange(s, 4).copyFormatToRange(ks, 7, 7, s, s);
      ks.getRange(s, 7).setValue(nm * nm1);
    break;
   }
  }
  for ( var s2 = 32; s2 <= 47; s2 = s2 + 3){
    var vm = ks.getRange(s2 - 2, 3).getValue();
    var vm1 = ks.getRange(s2 - 1, 3).getValue();
    var vm2 = ks.getRange(s2 - 2, 5).getValue();
    var vm3 = ks.getRange(s2 - 1, 5).getValue();
    if( ks.getRange(s2-1, 2).getValue() == "+"){
      ks.getRange(s2, 3).setValue(vm + vm1);
   }
   else if(ks.getRange(s2-1, 2).getValue() == "-"){
      ks.getRange(s2, 3).setValue(vm - vm1);
    }
   else if(ks.getRange(s2-1, 2).getValue() == "x"){
     ks.getRange(s2, 3).setValue(vm * vm1);
   }
     if( ks.getRange(s2-1, 4).getValue() == "+"){
      ks.getRange(s2, 5).setValue(vm2 + vm3);
    }
    else if(ks.getRange(s2-1, 4).getValue() == "-"){
     ks.getRange(s2, 5).setValue(vm2 - vm3);
    }
     else if(ks.getRange(s2-1, 4).getValue() == "x"){
      ks.getRange(s2, 5).setValue(vm2 * vm3);
    }
   }
 }

1 个答案:

答案 0 :(得分:0)

该问题涉及“数学”工作表,尤其是求解分数相加方程的问题。

该代码旨在为出现在第8至26行上的分数方程式更新“键”表上的结果。建立逻辑和机制后,提问者可以使用该代码来评估和更新公式在第30至47行中。

发问者应在其函数“ myWSG”中插入新行73,以创建“加号”,以确保加法适用于分数。当分数似乎要相乘而不是相加时,我在某一点上有轻微的心脏病发作。毫无疑问,已经建立了评估分数的机制,发问者可以将代码修改为分数的减法,乘法或除法。但这是发问者有空时最好做的事情。

myWSG第73行

ws.getRange(i, 4).setValue('+');

对分数的评估需要建立一个标题来管理各种选择和适当的处理方法。我已将此添加为附录。这包括评估零值分子(发问者可能预期或可能未预期)。

在每个分数都有不同分母的情况下,有必要建立一个“最低公分母”以使分数兼容。为此,我使用了“键”表上提供的LCM(最小公倍数)功能。唯一的问题是,这可能导致可以简化的部分。例如,如果答案是“ 1 26/40”,则可以将其简化为“ 1 13/20”。我将让提问者在闲暇时考虑其优缺点。


function so_52469576() {

  // build solutions for fractions
  // Define the sdpreadsheet and sheets
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var ks = ss.getSheetByName("Key");

  // set/reset key variables
  var status = 0;
  var numtotal = 0;
  var answer = 0;
  var IntegerDenominator = 0;
  var IntegerNumerator = 0;
  var answercell = "";
  var Remainder = 0;
  var answerInteger = 0;
  var seqL = 0;
  var newnumL = 0;
  var seqR = 0;
  var newnumR = 0;
  var numL = 0; 
  var denL = 0; 
  var numR = 0; 
  var denR = 0; 
  var lcd = 0; 

  // start loop for equations in lows 8 to 26, every other row
  for (var i = 8; i <= 26; i = i + 2){

    //Logger.log("i="+i);//DEBUG

    // ensure some variables values don't carry over
    // might not be necessary
    status = 0;
    numtotal = 0;
    answer = 0;
    IntegerDenominator = 0;
    IntegerNumerator = 0;
    answercell = "";
    Remainder = 0;
    answerInteger = 0;
    seqL = 0;
    newnumL = 0;
    seqR = 0;
    newnumR = 0;
    numL = 0; 
    denL = 0; 
    numR = 0; 
    denR = 0; 
    lcd = 0; 

    // collect denominators and numerators
    numL = ks.getRange(i,16).getValue(); 
    denL = ks.getRange(i,17).getValue(); 
    numR = ks.getRange(i,19).getValue(); 
    denR = ks.getRange(i,20).getValue(); 
    lcd= ks.getRange(i,22).getValue(); 
    //Logger.log("i="+i+",numL="+numL+", denL="+denL+",numR="+numR+", denR="+denR+", lcd="+lcd); //DEBUG

    // commence evaluation
    // 1- test for an integer
    // Left side first
     if ((denL == "n/a") || (denL == 1)){
       // Left side is an integer
       status = 1;
       //Logger.log("denl is an integer"); //DEBUG
     }
     else{
       // Left side must be a Fraction
       status = 2;
       // Logger.log("denl is NOT an integer"); //DEBUG
     }

     // Right side
     if ((denR == "n/a") || (denR == 1)){
       // Left side is an integer
       status = status+1;
       // Logger.log("denR is an integer"); // DEBUG
     }
     else{
       // Left side must be a Fraction
       status = status+2;
       // Logger.log("denR is NOT an integer"); //DEBUG
     }

     // possible status values
     // 2 = Two Integers
     // 3 = One Integer and one Fraction
     // 4 = Two Fractions
     // There aretwo variations to Two Fractions: 1 - Same denominators; 2 - Different Denominators

     if (status == 2){

       //Logger.log("Status = 2 - Two Integers");
       // Two integers
       //get the numerator
       numtotal = numL + numR;
       answer = numtotal;
       //Logger.log("i="+i+",Result 2");//DEBUG
       answercell = ks.getRange(i, 7);
       answercell.setValue(answer);
       // end status 2 - Two Integers


     } else if (status == 3){ 

       //Logger.log("Status = 3 - One Integer and One Fraction");//DEBUG
       // One Integer and One Fraction
       // establish which side is the integer

       if (denL == "n/a" || denL == 1){
         // the integer is on the left
         IntegerDenominator = denR; //row, column Col L
         IntegerNumerator = numL * IntegerDenominator; 
         numtotal = IntegerNumerator + numR; 
         //Logger.log("i="+i+",Result 3-1-1");//DEBUG

       }else{
         // the integer is on the right
         IntegerDenominator = denL; //row, column Col L
         IntegerNumerator = numR * IntegerDenominator;
         numtotal = IntegerNumerator + numL;
         // Logger.log("i="+i+",Result 3-1-2");// DEBUG
       }


       // test for a numerator equal to zero
       // no intergers are = zero 
       // no denominators = zero

       if (numL==0 && numR==0){

         // doesn't apply for one integer and one fraction, 
         // but retain for consistency
         // answer must be zero

         answer = 0; 
         // Logger.log("i="+i+",Result 3-1");// DEBUG

       } else if  (numL == 0) {

       // if numL is zero, then the fraction must be on the left side
       // integer must be on the right
       // so answer is an integer

       answer = numR;
         //Logger.log("i="+i+",Result 3-2");//DEBUG

       } 
       else if (numR == 0) {

         // if numR is zero, then the fraction must be on the right side
         // so integer must be on the left  
         // so answer is an integer
         answer = numL;
         // Logger.log("i="+i+",Result 3-3");DEBUG

       } 
       else {

         // neither side = zero, so answer as normal
         answerInteger = parseInt(numtotal / IntegerDenominator);
         Remainder = numtotal-(answerInteger * IntegerDenominator);
         answer = " "+answerInteger+" "+Remainder+"/"+IntegerDenominator;
         // Logger.log("i="+i+",Result 3-4");// DEBUG
       }

       answercell = ks.getRange(i, 7);
       answercell.setValue(answer);
       // end status 3

     } else {

       //Logger.log("Status = 4 - Two Fractions");
       // Two Fractions

       // test for a numerator equal to zero
       // no intergers are = zero 
       // no denominators = zero

       if (numL==0 && numR==0){

         // doesn't apply for one integer and one fraction, 
         // but retain for consistency
         // answer must be zero

         answer = 0;
         // DEBUGLogger.log("i="+i+",Result 4-1: ");

       } else if  (numL == 0) {

         // if numL is zero, then fraction on the left must = zero
         // so only the fraction on the right applies
         // so answer is the righthand side
         answer = " "+numR+" "+"/"+denR;  
         //Logger.log("i="+i+",Result 4-2");//DEBUG

       } else if  (numR == 0) {

         // if numR is zero, then fraction on the right must = zero
         // so only the fraction on the left applies
         // so answer is the lefthand side
         answer = " "+numL+" "+"/"+denLR;  
         // Logger.log("i="+i+",Result 4-3");//DEBUG

       } else if (denL == denR && numL !=0 && numR!=0){

         // establish whehther same or different demoninators
         // same denominators
         numtotal = numL + numR;
         answerInteger = parseInt(numtotal / denL);
         Remainder = numtotal-(answerInteger * denL);
         answer = " "+answerInteger+" "+Remainder+"/"+denL;
         // Logger.log("i="+i+",Result 4-4");// DEBUG
         // end same denominators

       }
       else if (denL != denR && numL !=0 && numR!=0)
       {

         // Test for different denominators
         // Requires calculating the Lowest Common Denominator

         seqL = (lcd/denL);
         newnumL = seqL * numL;
         seqR = (lcd/denR);
         newnumR = seqR * numR;
         numtotal = newnumL+ newnumR;
         answerInteger = parseInt(numtotal/lcd);
         Remainder = numtotal-(answerInteger * lcd);
         answer = " "+answerInteger+" "+Remainder+"/"+lcd;  
         // Logger.log("i="+i+",Result4-5");// DEBUG
         // end different denominators

       }
         answercell = ks.getRange(i, 7);
         answercell.setValue(answer); 

     }// end status 4 - Two Fractions  
   }// end for  
}// end

“密钥”表上的解决方案屏幕截图

enter image description here

规则-计算逻辑

需要建立方程式中的数字类型,以便我们可以应用适当的公式来求解。目的是区分整数和分数。在分数中,具有相同分母的那些和具有不同分母的那些。总体规则也适用,如果任一分数的分子为零,则其值为零,并且在计算中可以忽略它。

  • 计算非零分子的数目(可能是一或两个)
  • 计算非零分母的数目(可能是一或两个)
  • 添加结果(可能是两个,三个或四个)

可能的结果
两个整数”或“ 一个整数”和一个分数“或” 两个分数

两个整数
将两个数字相加并插入答案

一个整数和一个分数

  • 将整数转换为分数;获取分数的分母并创建一个具有相同值的分子

  • 添加两个分子

  • 将分子的总和除以分母,并表示为整数。

  • 计算分子的余数(分子的总和减去(分母的整数结果))

  • 答案=整数,空格和余数和//分母

两个部分 有两种变体

  • 每个分数具有相同的分母

  • 每个分数都有不同的分母

两个分数-分母相同

  • 添加分子

  • 将分子的和除以分母,并将结果表示为整数

  • 计算分子的余数(分子的总和减去(分母的整数结果))

  • 答案=整数,空格和余数和//分母

两个分数-分母不同

  • 找到最低公分母(LCM)

  • 对于每个部分,确定引起LCM的相应序列号

  • 对于每个分数,将分子乘以序列号;这会为每个分数生成一个“新”分子

  • 添加两个“新”分子

  • 用LCM划分分子的总和并表示为整数。

  • 计算分子的余数(“新”分子的总和减去(LCM的整数结果))

  • 答案=整数&space&remainder&/ && LCM


缺陷:最低的共同分母(LCD)。 该脚本依赖于“键”表上的LCM值。这使用Google函数“ LCM”来计算两个分母中的最小公倍数。 LCM并非总能生成真正的LCD,因为它正在求解公共乘数,而不是最小公分母。这永远不会是两个数字中的较小者。

例如

Assume the denominators are "6" and "2". The LCM value = 6, but the true Lowest common denominator is "2".