"
+ (fldnm
? document.getElementById(fldnm).innerHTML
:
"You can enter Numbers or Expressions:
" +
"
Operations:
+ - * /
Constants:
E PI Phi phi " +
"
Functions:
abs(real),pow(num,power),sqrt(real)
" +
"
sin,cos,tan,asin,acos,atan,
exp,log,log10,logBase(b,x)
" +
"
gcd(a,b),lcm(a,b),powmod(x,toPow,mod),EulerPhi
...
"
)
+ " ");
w.document.close();
w.focus()
return w
}
function showMoreOrLess(divId, incdec, btn) {
var newd,
v = document.getElementById(divId).style.height.replace("em", "");
if (!isNaN(v)) {
newd = eval(v) + incdec; //alert(newd);
if (newd < 15)newd = 15;
//alert("ht="+v+" new="+newd);
//v=newd;
document.getElementById(divId).style.height = newd + 'em'
if (document.getElementById(divId + "less")) {//alert('opac->'+newd+" "+(newd==15?0.1:1));
document.getElementById(divId + "less").style.opacity = (newd == 15 ? 0.1 : 1)
}
;
}
}
///////////////////////// HIDE and SHOW /////////////
function showhideIdBTN(info, btnID, d, Swop) {
if (arguments.length == 1) {
btnID = info + "BTN";
info = info + "DIV"
}
;
if (arguments.length <= 2)d = 'block';
if (arguments.length < 4)Swop = ["Hide", "Show"]
if (document.getElementById(btnID).value.match(Swop[0])) {
if (typeof info == "string")hideId(info)
else {
for (var i = 0; i < info.length; i++)hideId(info[i])
}
document.getElementById(btnID).value = document.getElementById(btnID).value.replace(Swop[0], Swop[1])
} else {
if (typeof info == "string")showId(info, d)
else {
for (var i = 0; i < info.length; i++)showId(info[i], d)
}
document.getElementById(btnID).value = document.getElementById(btnID).value.replace(Swop[1], Swop[0])
}
;
document.getElementById(btnID).blur();
}
;
function toggleBTN(btnId, Swop) {
var btn = document.getElementById(btnId);
if (!btn)halt("cannot toggle button " + btnId);
if (arguments.length == 1)Swop = ['Hide', "Show"];
if (btn.value.match(Swop[0]))
btn.value = btn.value.replace(Swop[0], Swop[1])
else btn.value = btn.value.replace(Swop[1], Swop[0])
btn.blur();
}
;
function hideId(nm) {
document.getElementById(nm).style.display = 'none'
}
;
function showId(nm, d) {
if (arguments.length == 1)d = 'block';
//alert('show '+nm+" -> "+d);
document.getElementById(nm).style.display = d;
}
function showhidetoggle(nm, d) {
if (arguments.length == 1)d = 'block';
if (document.getElementById(nm).style.display != 'none')
hideId(nm)
else showId(nm, d)
}
;
function toggle(id) { //Hide or show an element with given Id
var e = document.getElementById(id);
e.style.display = (e.style.display == '' ? 'none' : '');
}
function toggle2(id, link) {
//Hide or show an element with given Id and change
//text of the LINK accordingly....when calling, use "this" for arg 2 in onClick
var e = document.getElementById(id);
if (e.style.display == '') {
e.style.display = 'none';
link.innerHTML = 'More';
} else {
e.style.display = '';
link.innerHTML = 'Less';
}
}
function showhelpwin(visibQ) { //arg=true to show, false to hide it. Use puthelpwin(txt)
//alert((visibQ?"showing":"hiding"));
var w = document.getElementById("helpDIV");
w.style.display = (visibQ ? "block" : "none")
}
;
function puthelpwin()
//no args -> window is cleared
{
var w = document.getElementById("helpDIV"), txt = "";
if (arguments.length == 0) {
w.innerHTML = "";
return
}
for (var i = 0; i < arguments.length; i++)txt += arguments[i].toString();
w.innerHTML += txt + " ";
// w.scrollTop = w.scrollHeight;
// w.scrollLeft=0
}
;
function puthelpwinclose() {
puthelpwin("")
// with(document.getElementById("helpDIV"))
// {document.close();
// //focus()
// }
}
;
//////// see - use with VISIBILITY, not DISPLAY. They have white space until "seen"
function dontseeId(nm) {
if (arguments.length == 0)nm = "Soln";
if (document.getElementById) {
document.getElementById(nm).style.visibility = "hidden";
}
else if (document.all) {
document.all[nm].style.visibility = "hidden";
}
else if (document.layers) {
document[nm].visibility = "hide";
}
else {
var w = eval(nm).style;
w.visibility = "hidden"
}
;
}
;
function seeId(nm) {
if (arguments.length == 0)nm = "Soln";
if (document.getElementById) {
document.getElementById(nm).style.visibility = "visible";
}
else if (document.all) {
document.all[nm].style.visibility = "visible";
}
else if (document.layers) {
document[nm].visibility = "show";
}
else {
var w = eval(nm).style;
w.visibility = "visible"
}
;
}
;
function seetoggle(nm) {
var vis;
if (arguments.length == 0)nm = "Soln";
if (document.getElementById) {
vis = document.getElementById(nm).style.visibility == "visible";
}
else if (document.all) {
vis = document.all[nm].style.visibility == "visible";
}
else if (document.layers) {
vis = document[nm].visibility == "show";
}
;// else {var w=eval(nm).style;w.visibility="visible"};
if (vis) dontseeId(nm)
else seeId(nm)
}
;
function seedontIdBTN(info, btnID) {
if (arguments.length == 1)btnID = info;
if (document.getElementById(btnID).value.match('Hide')) {
if (arguments.length == 2)dontseeId(info);
document.getElementById(btnID).value = document.getElementById(btnID).value.replace('Hide', 'Show')
} else {
if (arguments.length == 2)seeId(info);
document.getElementById(btnID).value = document.getElementById(btnID).value.replace('Show', 'Hide')
}
;
document.getElementById(btnID).blur();
}
;
///////////////////////////////
function setStyle(nm, valpair) {
if (arguments.length == 0)nm = "Soln";
var attr = valpair.slice(0, valpair.indexOf(":")), attrval = valpair.slice(valpair.indexOf(":") + 1);
if (document.getElementById) {
document.getElementById(nm).style[attr] = attrval
}
else if (document.all) {
document.all[nm].style[attr] = attrval
}
else if (document.layers) {
document[nm][attr] = attrval
}
else {
var w = eval(nm).style;
w[attr] = attrval
}
;
}
;
function findpos(obj) {
var curleft = 0, curtop = 0;
if (obj.offsetParent)
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return [curleft, curtop];
}
/////////////// SET Object
function isEltOfArray(elt, a) {
var found = false;
for (var i = 0; !found && i < a.length; i++)found = (a[i] == elt);
return found
}
;
function ASSOCARR() { // as is an array of [elt,otherinfo]. Return [otherinfo] for all elt in as
this.eltvals = new Array();
}
;
ASSOCARR.prototype.length = function () {
return this.eltvals.length
}
ASSOCARR.prototype.push = function (elt, info) {
for (var i = 0; i < this.eltvals.length; i++)
if (this.eltvals[i][0] == elt) {
this.eltvals[i][1].push(info);
return
}
this.eltvals.push([elt, [info]])
};
ASSOCARR.prototype.assoc = function (elt) {
for (var i = 0; i < this.eltvals.length; i++)
if (this.eltvals[i][0] == elt)return this.eltvals[i][1];
return []
};
ASSOCARR.prototype.index = function (elt) {
for (var i = 0; i < this.eltvals.length; i++)
if (this.eltvals[i][0] == elt)return i
return -1
};
ASSOCARR.prototype.sort = function () {
this.eltvals.sort(function (a, b) {
return a[0] - b[0]
})
};
ASSOCARR.prototype.toString = function (colon, comma, ender) {
var s = "";
if (arguments.length < 1)colon = ":";
if (arguments.length < 2)comma = ",";
if (arguments.length < 3)ender = " ";
for (var i = 0; i < this.eltvals.length; i++)s += this.eltvals[i][0] + colon + this.eltvals[i][1].join(comma) + ender;
return s
};
ASSOCARR.prototype.concat = function (assocs) {
// all elts of assocs are added into THIS with their associated vals
for (var i = 0; i < assocs.length(); i++) {
var ev = assocs.eltvals[i];
for (var j = 0; j < ev[1].length; j++)this.push(ev[0], ev[1][j])
}
};
ASSOCARR.prototype.extend = function (assocs, where) {
//only those elts of assocs already in THIS have their associations extended
//where is "-1" for end, "0" for beginning
var ind, i;//alert("extending with "+assocs.length());
if (arguments.length < 2)where = -1;
for (i = 0; i < assocs.length(); i++)
if ((ind = this.index(assocs.eltvals[i][0])) > -1)
if (where == -1)
for (j = 0; j < assocs.eltvals[i][1].length; j++)
this.eltvals[ind][1].push(assocs.eltvals[i][1][j])
else
for (j = assocs.eltvals[i][1].length; j >= 0; j--)
this.eltvals[ind][1].unshift(assocs.eltvals[i][1][j])
};
function Arraypos(elt, a) {
var found = false;
for (var i = 0; !found && i < a.length; i++)if (a[i] == elt)break;
return (i == a.length ? -1 : i)
}
;
function SET(els) {
if (els.setsize) //copy SET
{
this.elts = els.elts.slice();
this.setsize = els.setsize;
return
}
;
this.elts = new Array();
for (var i = 0; i < els.length; i++)
if (!isEltOfArray(els[i], this.elts))this.elts.push(els[i]);
this.setsize = this.elts.length;
}
;
SET.prototype.newElt = function (e) {
this.elts.push(e);
this.setsize++
};
function isInSET(e, s) {
return isEltOfArray(e, s.elts)
}
;
function SETunion(s1, s2) {
var u = new SET(s1);
for (var i = 0; i < s2.setsize; i++)
if (!isInSET(s2.elts[i], u))u.newElt(s2.elts[i]);
return u
}
function SETintersection(s1, s2) {
var I = new SET();
for (var i = 0; i < s1.setsize; i++)
if (isInSet(s1.elts[i], s2))I.newElt(s1.elts[i]);
return I
}
;
function SETdiff(s1, s2) {
var D = new SET();
for (var i = 0; i < s1.setsize; i++)
if (!isInSet(s1.elts[i], s2))D.newElt(s1, elts[i]);
return D
}
/////////////////// ARR Object - Array allowing -ve indices
function ARR(lo, hi, mt) {//a JS array type which allows -ve indices
//putmsg("ARR "+lo+" "+hi+" "+mt)
if (arguments.length < 3)mt = 0;
this.empty = mt;
this.lwb = lo;
this.upb = hi;
this.elts = new Array(hi - lo + 1);
for (var i = 0; i < hi - lo + 1; i++)this.elts[i] = this.empty;
this.length = this.upb - this.lwb + 1;
}
ARR.prototype.at = function (i) {
if (this.inrange(i)) {
return this.elts[i - this.lwb]
} else return this.empty
};
ARR.prototype.set = function (ind, val) {
if (ind < this.lwb) {
var extra = new Array();
for (var i = this.lwb - 1; i >= ind; i--)extra[i - ind] = this.empty;
this.lwb = ind;
this.elts = extra.concat(this.elts)
}
else if (ind > this.upb) {
var extra = new Array();
for (var i = 0; i < ind - this.upb; i++)extra[i] = this.empty;
this.upb = ind;
this.elts = this.elts.concat(extra)
}
this.elts[ind - this.lwb] = val
};
ARR.prototype.inc = function (i, addon) {
var currval = this.at(i);
this.set(i, currval + addon)
};
ARR.prototype.toString = function () {
return this.elts
};
ARR.prototype.inrng = function (lind, rind) {
return this.elts.slice(lind - this.lwb, rind - this.lwb + 1)
}
function reversearray(a) {
return a.slice().reverse()
}
;
function changeOpac(opacity, id) {
var object = document.getElementById(id).style;
object.opacity = (opacity / 100);
object.KhtmlOpacity = (opacity / 100);
}
function RANGE(f, t) {
this.from = f;
this.to = t;
this.size = t - f + 1;
}
;
RANGE.prototype.toString = function () {
return (this.from == this.to ? this.from : this.from + rangech + this.to)
}
function RANGEby(f, len) {
return new RANGE(f, f + len - 1)
}
;
function stringhasRANGE(str, sub) {
// alert(str+" :: "+sub)
return RANGEby(str.indexOf(sub), sub.length)
}
;
// Use a div:
//
//
//
//
//
// then change image with
//
//
function blendimage(divid, imageid, imagefile, millisec) {
var speed = Math.round(millisec / 100);
var timer = 0, tID;
//set the current image as background
document.getElementById(divid).style.backgroundImage = "url(" + document.getElementById(imageid).src + ")";
//make image transparent
changeOpac(0, imageid);
//make new image
document.getElementById(imageid).src = imagefile;
//fade in image
for (var i = 0; i <= 100; i++) {
tID = setTimeout("changeOpac(" + i + ",'" + imageid + "')", (timer * speed));
timer++;
}
;
clearTimeout(tID);
}
function changeStyle(objID, stypairs) { // style:value separator=;
var S = document.getElementById(objID).style;
var pairs = stypairs.split(";");
for (var i = 0; i < pairs.length; i++) {
var pos = pairs[i].indexOf(":");
if (pos == -1)S[pairs[i]] = true //allow ids with no values
else S[pairs[i].substring(0, pos)] = pairs[i].substring(pos + 1);
}
;
}
;
function resizeIMG(imgID, w, h) {
if (arguments.length < 3)halt("$$ resize img needs width and height");
var i = document.getElementById(imgID);
if (!i)halt("$$ There is no image called " + imgID + " to resize");
i.width = w;
i.height = h
}
;
function changeProp(objID, proppairs) { //prop=value separator=,
var S = document.getElementById(objID);
var pairs = proppairs.split(",");
for (var i = 0; i < pairs.length; i++) {
var pos = pairs[i].indexOf("=");
if (pos == -1)S[pairs[i]] = true //allow ids with no values
else S[pairs[i].substring(0, pos)] = pairs[i].substring(pos + 1);
}
;
}
;
///////////// COLOURS ////////////
var colvals = [
["AliceBlue", "#F0F8FF"],
["AntiqueWhite", "#FAEBD7"],
//["Aqua","#00FFFF"], //== Cyan
["Aquamarine", "#7FFFD4"],
["Azure", "#F0FFFF"],
["Beige", "#F5F5DC"],
["Bisque", "#FFE4C4"],
["Black", "#000000"],
["BlanchedAlmond", "#FFEBCD"],
["Blue", "#0000FF"],
["BlueViolet", "#8A2BE2"],
["Brown", "#A52A2A"],
["BurlyWood", "#DEB887"],
["CadetBlue", "#5F9EA0"],
["Chartreuse", "#7FFF00"],
["Chocolate", "#D2691E"],
["Coral", "#FF7F50"],
["CornflowerBlue", "#6495ED"],
["Cornsilk", "#FFF8DC"],
["Crimson", "#DC143C"],
["Cyan", "#00FFFF"],
["DarkBlue", "#00008B"],
["DarkCyan", "#008B8B"],
["DarkGoldenRod", "#B8860B"],
["DarkGray", "#A9A9A9"],
["DarkGreen", "#006400"],
["DarkKhaki", "#BDB76B"],
["DarkMagenta", "#8B008B"],
["DarkOliveGreen", "#556B2F"],
["DarkOrange", "#FF8C00"],
["DarkOrchid", "#9932CC"],
["DarkRed", "#8B0000"],
["DarkSalmon", "#E9967A"],
["DarkSeaGreen", "#8FBC8F"],
["DarkSlateBlue", "#483D8B"],
["DarkSlateGray", "#2F4F4F"],
["DarkTurquoise", "#00CED1"],
["DarkViolet", "#9400D3"],
["DeepPink", "#FF1493"],
["DeepSkyBlue", "#00BFFF"],
["DimGray", "#696969"],
["DodgerBlue", "#1E90FF"],
["FireBrick", "#B22222"],
["FloralWhite", "#FFFAF0"],
["ForestGreen", "#228B22"],
//["Fuchsia","#FF00FF"], //=Magenta
["Gainsboro", "#DCDCDC"],
["GhostWhite", "#F8F8FF"],
["Gold", "#FFD700"],
["GoldenRod", "#DAA520"],
["Gray", "#808080"],
["Green", "#008000"],
["GreenYellow", "#ADFF2F"],
["HoneyDew", "#F0FFF0"],
["HotPink", "#FF69B4"],
["IndianRed", "#CD5C5C"],
["Indigo", "#4B0082"],
["Ivory", "#FFFFF0"],
["Khaki", "#F0E68C"],
["Lavender", "#E6E6FA"],
["LavenderBlush", "#FFF0F5"],
["LawnGreen", "#7CFC00"],
["LemonChiffon", "#FFFACD"],
["LightBlue", "#ADD8E6"],
["LightCoral", "#F08080"],
["LightCyan", "#E0FFFF"],
["LightGoldenRodYellow", "#FAFAD2"],
["LightGray", "#D3D3D3"],
["LightGreen", "#90EE90"],
["LightPink", "#FFB6C1"],
["LightSalmon", "#FFA07A"],
["LightSeaGreen", "#20B2AA"],
["LightSkyBlue", "#87CEFA"],
["LightSlateGray", "#778899"],
["LightSteelBlue", "#B0C4DE"],
["LightYellow", "#FFFFE0"],
["Lime", "#00FF00"],
["LimeGreen", "#32CD32"],
["Linen", "#FAF0E6"],
["Magenta", "#FF00FF"], //==Fuchsia
["Maroon", "#800000"],
["MediumAquaMarine", "#66CDAA"],
["MediumBlue", "#0000CD"],
["MediumOrchid", "#BA55D3"],
["MediumPurple", "#9370DB"],
["MediumSeaGreen", "#3CB371"],
["MediumSlateBlue", "#7B68EE"],
["MediumSpringGreen", "#00FA9A"],
["MediumTurquoise", "#48D1CC"],
["MediumVioletRed", "#C71585"],
["MidnightBlue", "#191970"],
["MintCream", "#F5FFFA"],
["MistyRose", "#FFE4E1"],
["Moccasin", "#FFE4B5"],
["NavajoWhite", "#FFDEAD"],
["Navy", "#000080"],
["OldLace", "#FDF5E6"],
["Olive", "#808000"],
["OliveDrab", "#6B8E23"],
["Orange", "#FFA500"],
["OrangeRed", "#FF4500"],
["Orchid", "#DA70D6"],
["PaleGoldenRod", "#EEE8AA"],
["PaleGreen", "#98FB98"],
["PaleTurquoise", "#AFEEEE"],
["PaleVioletRed", "#DB7093"],
["PapayaWhip", "#FFEFD5"],
["PeachPuff", "#FFDAB9"],
["Peru", "#CD853F"],
["Pink", "#FFC0CB"],
["Plum", "#DDA0DD"],
["PowderBlue", "#B0E0E6"],
["Purple", "#800080"],
["Red", "#FF0000"],
["RosyBrown", "#BC8F8F"],
["RoyalBlue", "#4169E1"],
["SaddleBrown", "#8B4513"],
["Salmon", "#FA8072"],
["SandyBrown", "#F4A460"],
["SeaGreen", "#2E8B57"],
["SeaShell", "#FFF5EE"],
["Sienna", "#A0522D"],
["Silver", "#C0C0C0"],
["SkyBlue", "#87CEEB"],
["SlateBlue", "#6A5ACD"],
["SlateGray", "#708090"],
["Snow", "#FFFAFA"],
["SpringGreen", "#00FF7F"],
["SteelBlue", "#4682B4"],
["Tan", "#D2B48C"],
["Teal", "#008080"],
["Thistle", "#D8BFD8"],
["Tomato", "#FF6347"],
["Turquoise", "#40E0D0"],
["Violet", "#EE82EE"],
["Wheat", "#F5DEB3"],
["White", "#FFFFFF"],
["WhiteSmoke", "#F5F5F5"],
["Yellow", "#FFFF00"],
["YellowGreen", "#9ACD32"]];
var cols = new Array();
function cutHex(h) {
return (h.charAt(0) == "#" ? h.substring(1, 7) : h)
}
;
function hexslice(h, s0, send) {
return parseInt((cutHex(h)).substring(s0, send), 16)
}
;
function hexToRGB(s) { // return array of 3 ints in range 0..255
return [hexslice(s, 0, 2), hexslice(s, 2, 4), hexslice(s, 4, 6)]
}
;
function brightness(rgb, fs) { //return brightness in range 0..255
//if(!confirm(fs))ERROR();
if (arguments.length < 2)fs = [0.25, 0.7, 0.05]
//[0.241,0.691,0.068] //http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
// [0.299,.587,.114] //http://alienryderflex.com/hsp.html
var r, g, b; //0..255
if (typeof rgb == "string") {
r = hexslice(rgb, 0, 2);
g = hexslice(rgb, 2, 4);
b = hexslice(rgb, 4, 6)
}
else if (rgb.length) {
r = rgb[0];
g = rgb[1];
b = rgb[2]
}
;
return Math.sqrt(r * r * fs[0] + g * g * fs[1] + b * b * fs[2])
}
;
function rgbI(rgbstr, rf, gf, bf) { //return brightness in range 0--255, 0=black, 255=white
if (arguments.length == 0) {
rf = 0.22;
gf = 0.7;
bf = 0.08
}
;
// var rgb=hexToRGB(rgbstr);
// return (Math.max(rgb[0],Math.max(rgb[1],rgb[2]))+Math.min(rgb[0],Math.min(rgb[1],rgb[2])))/2};
return Math.round(rf * hexslice(rgbstr, 0, 2) + gf * hexslice(rgbstr, 2, 4) + bf * hexslice(rgbstr, 4, 6))
}
;
function rgbToHex(R, G, B) {
return toHex(R) + toHex(G) + toHex(B)
}
function toHex(n) {
n = parseInt(n, 10);
if (isNaN(n)) return "00";
n = Math.max(0, Math.min(n, 255));
return "0123456789ABCDEF".charAt((n - n % 16) / 16)
+ "0123456789ABCDEF".charAt(n % 16);
}
function rgbfracHex(r, g, b)// r,g,b are in 0..1
{
return "#" + rgbToHex(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255))
}
;
function ColGrad(nbsteps, stepnb) { // stepnb in 0..(nbsteps-1); returns #rrggbb string
//max,min in 0..1; pastels:min=0.5
var l = cols.length;
if (isNaN(stepnb))return "#FFFFDD"; //colvals[l/nbsteps*nbsteps][1]
return cols[Math.round(l / nbsteps * (stepnb + 0.5))]
}
;
function GrayGrad(nbsteps, stepnb) {
if (isNaN(stepnb))return "#FFFFDD";
var f = (1 - stepnb / nbsteps);
return rgbfracHex(f, f, f)
}
;
function initcols() {
colvals.sort(function (a, b) {
return brightness(a) - brightness(b)
});
for (var r = 25; r < 256; r += 17)
for (var g = 25; g < 256; g += 17)
for (var b = 25; b < 256; b += 17)
cols.push("#" + rgbToHex(r, g, b));
cols.sort(function (a, b) {
return brightness(a) - brightness(b)
});
}
initcols()
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function RAT(t, b) { // if infinite, sets t=1 and b=0
if (!isZ(t))halt("Cant make Q from num:" + t);
if (!isZ(b))halt("cant make Q from den:" + b);
var tt = (t < 0 ? -t : t), bb = (b < 0 ? -b : b);
if (b == 0) {
t = (t > 0 ? 1 : -1)
}
else {
var g = gcd(tt, bb);
if (g > 1) {
t = Math.round(t / g);
b = Math.round(b / g)
}
}
;
if (b < 0) {
t = -t;
b = -b
}
this.top = NB(t);
this.bot = NB(b);
this.isfinite = this.b != 0;
this.toString = function () {
return (this.isfinite ? (this.bot == 1 ? this.top.toString()
: this.top.toString() + "/" + this.bot.toString() + "")
: (this.top < 0 ? "-" : "") + "Infinity")
};
this.val = NB(t / b);
this.sgnum = (this.top < 0 ? -1 : this.top == 0 ? 0 : 1);
}
;
function RATmul(a, b) {
if (typeof a == "number")a = new RAT(a, 1);
if (typeof b == "number")b = new RAT(b, 1);
return new RAT(a.top * b.top, a.bot * b.bot)
}
;
function RATdiv(a, b) {
if (typeof a == "number")a = new RAT(a, 1);
if (typeof b == "number")b = new RAT(b, 1);
return new RAT(a.top * b.bot, a.bot * b.top)
}
;
function RATadd(a, b) {
if (typeof a == "number")a = new RAT(a, 1);
if (typeof b == "number")b = new RAT(b, 1);
return new RAT(a.top * b.bot + b.top * a.bot, a.bot * b.bot)
}
;
function RATsub(a, b) {
if (typeof a == "number")a = new RAT(a, 1);
if (typeof b == "number")b = new RAT(b, 1);
return RATadd(a, RATneg(b))
}
;
function RATneg(a) {
return (typeof a == "number" ? new RAT(-a, 1) : new RAT(-a.top, a.bot))
}
;
function RATis(a, op, b) {
if (typeof a == "number")a = new RAT(a, 1);
if (typeof b == "number")b = new RAT(b, 1);
var L = a.top * b.bot, R = a.bot * b.top;
return eval(isFinite(L) && isFinite(R) ? L + op + R : a.val + op + b.val)
}
;
function RATmediant(R1, R2) {
return new RAT(R1.top + R2.top, R1.bot + R2.bot)
}
;
var toosmall = 0.0000000001, toolarge = 100000;
function NB(x) {
if (Math.abs(Math.round(x) - x) <= toosmall)return Math.round(x)
else if (x > toolarge)return Number.POSITIVE_INFINITY
else if (x < -toolarge)return Number.NEGATIVE_INFINITY
else return x
}
;
function norm(x) {
//if(isPOLY(x)&&x.deg==0){x=POLYcoeff(x,0)};
//if(isC(x)&&NB(Cim(x))==0){x=Cre(x)};
if (isQ(x) && x.bot == 1) {
x = x.top
}
;
if (isR(x) && Math.abs(Math.round(x) - x) < toosmall)x = Math.round(x);
return x
}
;
function Z2Q(n) {
return new RAT(n, 1)
}
;
//function Q2C(r){return new COMPLX(r,0)};
function Q2R(x) {
return x.val
}
;
//function R2C(x){return new COMPLX(x,0)};
function isZ(x) {
return !isNaN(x) && isFinite(x) && x.toString().indexOf(".") == -1 && eval(x) + 1 != x
}
;
function isR(x) {
return !isNaN(x) && isFinite(x) && x.toString().indexOf(".") != -1
}
;
function isNb(x) {
return isZ(x) || isR(x)
}
;
function isQ(x) {
return typeof x == "object" && x.top
}
; //x instanceof RAT }
//function isC(x){return typeof x=="object" && x.im}; //x instanceof COMPLX};
function isfinite(n) {
return isQ(n) ? n.isfinite : isFinite(n)
}
;
function isInfinite(x) {
return isQ(x) && !x.isfinite //|| !isC(x) &&!isfinite(x)
}
;
var notyp = "?no-type?"
function typ(x) {
return isZ(x) ? "Z" : isR(x) ? "R" : isQ(x) ? "Q"//:isC(x)?"C":isPOLY(x)?"P"
: notyp
}
;
function isString(s) {
return typeof s == "string"
}
;
//function toC(x){if(typ(x)=="C"){return x }else{ return [x,0]}};
function toQ(x) {
switch (typ(x)) {
case "Q":
return x;
// case "C":halt("Cant convert CtoQ "+C);
case "R":
halt("Cant convert RtoQ " + x);
case "Z":
return Z2Q(x);
}
}
;
function toR(x) {
if (isQ(x))return x.val;
//if(isC(x)){if(x[1]==0){return x[0]}else{halt("Cant convert CtoR:"+x)}};
if (isNb(x))return x;
}
;
function add(x, y) {//document.writeln(">>> ",typeof x,"=",x," ",typeof y,"=",y);
if (isInfinite(x) && isInfinite(y)) return (cmp(x, ">", 0) == cmp(y, ">", 0) ? x : Number.NaN)
else if (isInfinite(x))return x
else if (isInfinite(y))return y
else if (isR(x) || isR(y))return norm(toR(x) + toR(y))
else if (isQ(x) || isQ(y)) {
x = toQ(x);
y = toQ(y);
return norm(RATadd(x, y))
}
;
return norm(NB(eval(x) + eval(y)));
}
;
function sub(x, y) {
return add(x, neg(y))
}
;
function neg(x) {
if (isNb(x))return -x;
if (isInfinite(x))return -x;
if (isQ(x))return RATneg(x);
halt("??? negate " + x)
}
;
function mul(a, b) {
if (isInfinite(a))return (b == 0 ? Number.NaN : cmp(b, ">", 0) ? a : -a)
else if (isInfinite(b))return (a == 0 ? Number.NaN : cmp(a, ">", 0) ? b : -b)
// else if(isC(a)||isC(b)){a=toC(a);b=toC(b);return norm(Cmul(a,b))}
else if (isR(a) || isR(b))return norm(toR(a) * toR(b));
else if (isQ(a) || isQ(b)) {
a = toQ(a);
b = toQ(b);
return norm(RATmul(a, b))
}
return norm(a * b)
}
;
function mod(a, b) {
if (isInfinite(b))return (!isInfinite(a) ? a : Number.NaN);
if (isZ(a) && isZ(b))return a % b
return Number.NaN
}
;
function div(n, d) {//alert("div "+typ(n)+" "+typ(d));
if (isR(n) || isR(d)) {
n = toR(n);
d = toR(d);
return norm(NB(n / d))
}
;
//alert(n+" mod "+d+" = "+mod(n,d)+" flr="+Math.floor(n/d));
if (isZ(n) && isZ(d))
if (mod(n, d) == 0)return norm(Math.round(n / d))
else return norm(new RAT(n, d));
n = toQ(n);
d = toQ(d);
return norm(RATdiv(n, d))
}
;
function pow(a, b) {//alert("pow "+typ(a)+"^"+typ(b));
if (isQ(b))b = b.val;
if (isQ(a)) {
if (isZ(b) && b < 0)return new RAT(Math.pow(a.bot, -b), Math.pow(a.top, -b))
else return new RAT(Math.pow(a.top, b), Math.pow(a.bot, b))
}
;
a = toR(a);
return norm(NB(Math.pow(a, b)))
}
;
function cmp(a, op, b) {
if (op == "=")op = "==";
if (isQ(a) || isQ(b)) {
a = toQ(a);
b = toQ(b);
return RATis(a, op, b)
}
;
return eval(a + op + b)
}
;
function abs(x) {
if (cmp(x, "<", 0))x = neg(x);
return x
}
;
function num(n) {
return isQ(n) ? n.top : n
}
;
function den(n) {
return isQ(n) ? n.bot : 1
}
;
////////////////////////////////////////////////////////////////////////////////////////////////////
function CF() {
this.cf = new Array(); // cf[0] is always the integer part
this.cfrec = new Array();
this.cvgt = new Array();
this.stopped = false;
this.cfOFLO = false;
this.cvgt[-1] = new RAT(1, 0, 'bot0');
}
;
CF.prototype.norm = function () {
while (this.cf.length > 1 && this.cfrec.length > 0 && this.cf[this.cf.length - 1] == this.cfrec[this.cfrec.length - 1]) {//putmsg("norming");
this.cfrec.pop();
this.cfrec.unshift(this.cf.pop())
}
;
};
CF.prototype.termat = function (i) { // indexed from 0
if (i < 0)HALT("CF has no term with index " + i);
if (i < this.cf.length)return this.cf[i];
if (this.isPeriodic())
return this.cfrec[(i - this.cf.length) % this.cfrec.length]
else HALT("CF has no term at index " + i);
};
CF.prototype.append =
function (cfterm, cvgtQ) {
if (arguments.length < 2)cvgtQ = false;
//putmsg("append "+cfterm);
if (cfterm < 0)HALT("CF terms must be positive");
if (this.cf.length > 100) {
this.cfOFLO = true;
return
}
//if(this.cfint==-1)this.cfint=cfterm
//else
this.cf[this.cf.length] = cfterm;
if (cvgtQ && !this.stopped) {
if (this.cf.length == 1) {
this.cvgt[-1] = new RAT(1, 0, 'bot0');
this.cvgt[0] = new RAT(cfterm, 1)
}
else {
var T = this.cvgt[this.cvgt.length - 1].top * cfterm + this.cvgt[this.cvgt.length - 2].top,
B = this.cvgt[this.cvgt.length - 1].bot * cfterm + this.cvgt[this.cvgt.length - 2].bot;
if (isZ(B))this.cvgt[this.cvgt.length] = new RAT(T, B)
else this.cvgt.length++;
//putmsg("cvgt---"+this.cf[i]+":"+this.cvgt[this.cvgt.length-1].top+"/"+this.cvgt[this.cvgt.length-1].bot);
this.stopped = !isZ(B) ||
(this.cvgt.length > 2 &&
( this.cvgt[this.cvgt.length - 1].top / this.cvgt[this.cvgt.length - 1].bot
== this.cvgt[this.cvgt.length - 2].top / this.cvgt[this.cvgt.length - 2].bot));
if (this.stopped) {
this.cvgt.length = this.cvgt.length - 1;
}
}
}
;
};
CF.prototype.cvgts = function () {//putmsg("periodic:"+this.isPeriodic());
this.cvgt[-1] = new RAT(1, 0, 'bot0');
this.cvgt[0] = new RAT(this.cf[0], 1)
for (var i = 1; !this.stopped && (this.isPeriodic() || i < this.cf.length) && i < 40; i++) {//putmsg("cvgt@"+i+" of "+this.cf.length);
this.cvgt[this.cvgt.length] = new RAT(this.cvgt[this.cvgt.length - 1].top * this.termat(i) + this.cvgt[this.cvgt.length - 2].top,
this.cvgt[this.cvgt.length - 1].bot * this.termat(i) + this.cvgt[this.cvgt.length - 2].bot);
//putmsg("cvgt---"+this.cf[i]+":"+this.cvgt[this.cvgt.length-1].top+"/"+this.cvgt[this.cvgt.length-1].bot);
this.stopped = this.cvgt.length > 2 &&
( this.cvgt[this.cvgt.length - 1].top / this.cvgt[this.cvgt.length - 1].bot
== this.cvgt[this.cvgt.length - 2].top / this.cvgt[this.cvgt.length - 2].bot);
if (this.stopped) {
this.cvgt.length = this.cvgt.length - 1;
}
}
;
//putmsgto("res","CVGTS......this.cvgt.length="+this.cvgt.length);
//cfSHOW();
};
CF.prototype.reset =
function () {
this.cf.length = 0;
this.cvgt.length = 0;
this.stopped = false; //this.cvgtUPB=-1;
this.cfrec.length = 0;
this.cfOFLO = false;
};
CF.prototype.isUnset = function () {
return this.cf.length == 0
};
CF.prototype.lastcf =
function () {
return this.cf[this.cf.length - 1]
};
CF.prototype.pop =
function () {
if (this.stopped || this.cf.length == 0 || this.isPeriodic())return;
var x = this.lastcf(); //this.cvgt.length=this.cvgt.length-1;
this.cf.length = this.cf.length - 1;
return x
};
CF.prototype.altcf =
function () {//putmsg("CF---altcf of "+this.cftoString());
if (this.stopped)halt("The CF is not exact so has no alternate form");
if (this.cf.length == 0)halt("The CF has no value");
if (this.isZero())halt("The CF is 0 and has no alternate form");
if (this.isPeriodic())halt("The CF is periodic so never ends");
var last = this.pop();
if (this.cf.length > 0 && last == 1)this.append(this.pop() + 1)
else {
this.append(last - 1);
this.append(1)
}
return true;
};
CF.prototype.isZero = function () {
return this.cf.length == 1 && this.cf[0] == 0 && this.cfrec.length == 0
};
CF.prototype.isPeriodic = function () {
return this.cfrec.length > 0
};
CF.prototype.cftoString =
function () { //alert("PERIODIC? "+this.isPeriodic()+" "+this.cfperiodLWB+".."+this.cfperiodUPB);
//putmsg(this.isPeriodic()+" "+this.cfrec +" stp="+this.stopped);
var s = "[" + this.cf[0] + "; " + this.cf.slice(1).join(", ");
if (this.isPeriodic()) {
if (this.cf.length > 1)s = s + ",";
s = s + " " + this.cfrec.join(", ") + ""
}
else if (this.stopped) s += " ...";
s = s + "]"
return s
};
CF.prototype.cvgtstoString =
function () {
var s = "Convergents of " + this.cftoString() + ": ";
//Cf.cvgt.slice(0,this.cvgtUPB+1).join(", ")+(this.stopped?" ...":"");
for (i = 0; i < this.cvgt.length; i++)
s = s + this.termat(i) + ": " + this.cvgt[i] + " = " + this.cvgt[i].top / this.cvgt[i].bot + " ";
if (this.stopped)s = s + "... ";
return s
};
CF.prototype.toRAT =
function () { //alert("toRAT: "+this.cftoString()+" cvgts end at "+this.cvgt.length-1);
return this.cvgt[this.cvgt.length - 1]
};
CF.prototype.toDec = function () {
return eval(this.toRAT().toString())
};
CF.prototype.toString = function () {
return this.cftoString() + " with " + this.cvgts.length + " cvgts"
};
CF.prototype.dump = function () {
return "===DUMP cf=" + this.cf.join(",") +
"[" + this.cfrec.join(",") + "] " + this.cvgt.length + "=#cvgt " +
" stopped=" + this.stopped + " OFLO=" + this.cfOFLO
+ " 0?=" + this.isZero() + " ===== "
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function DoERROR() {
return false
}
;
function resetERROR() {
self.onerror = DoERROR;
return true
}
;
function HALT(msg) {
alert("警告\r" + msg);
self.onerror = resetERROR;
ERROR();
alert("aagh - after HALT")
}
;
var ErrorAt = "", ErrorIn = "";
function ERRORHandler(msg, error, line) {
alert("有一个问题 " + ErrorAt + ":\r" + ErrorIn + " 不是一个有效数字.");
return true
}
;
// Make a window Pop Up
var debug = false, record = false;
var _auxwin;
if (debug) {
_auxwin = window.open("", "tip", "width=500,height=400,scrollbars=yes,resizable=yes,status=yes");
_auxwin.document.open("text/plain")
}
;
function _AuxWinOpen(typ) { //default typ=="html"
//alert(typ);
_auxwin = window.open("", "tip", "width=500,height=400,scrollbars=yes,resizable=yes,status=yes");
//if already open, does nothing
//if(typ && typ=="plain"){_auxwin.document.open("text/plain")}else{_auxwin.document.open()};
_auxwin.focus()
}
;
function DBG(args) { //no args means clear _auxwin window
if (!debug)return;
if (arguments.length == 0) {
_auxwin.document.close();
_auxwin.document.open("text/plain");
}
else {
for (var i = 0; i < arguments.length; i++)
_auxwin.document.write(arguments[i]);
_auxwin.document.writeln();
}
;
}
;
function getRNS() {
var r = isINT(getElementById("R").value, "the first number in the numerator of the Fraction", 0),
n = isINT(getElementById("N").value, "the value square-rooted in the numerator of the Fraction", 0),
s = isINT(getElementById("S").value, "the denominator of the Fraction", 1);
if (n < 0)HALT("The square-root of a negative number is not allowed.");
if (getSEL("SGN").value == "-" || s < 0 && r < 0 && n == 0) {
r = -r;
s = -s
}
;
return {R: r, N: n, S: s}
}
;
function setRNS(r, n, s) {
if (r == "")r = 0;
if (n == "")n = 0;
if (s == "")s = 1;
if (s < 0) {
r = -r;
s = -s;
getElementById("SGN").selectedIndex = 1
} else {
getElementById("SGN").selectedIndex = 0
}
;
getElementById("R").value = (r == 0 ? "" : r);
getElementById("N").value = (n == 0 ? "" : n);
getElementById("S").value = (s == 1 ? "" : s)
}
;
function showrns(r, k, n, s) { // ( r+ksqrt(n) )/s
if (debug)DBG("show(" + r + "," + k + "," + n + "," + s + ")");
if (s < 0) {
r = -r;
k = -k;
s = -s
}
;
var top = (r != 0 ? r : "")
+ (n != 0 ? (r != 0 && k > 0 ? "+" : k < 0 ? "-" : "")
+ (Math.abs(k) != 1 ? Math.abs(k) : "")
+ "√" + n
: "");
return (s != 1 ? (n == 0 || r == 0 ? "" : "(") : "")
+ top +
(s != 1 ? (n == 0 || r == 0 ? "" : ")") : "")
+ (s == 1 ? "" : "/" + s)
}
;
function showrnsdc(r, n, s, d, c) {
if (debug)DBG("showrnsdc(" + r + "," + n + "," + s + "," + d + "," + c + ")");
var k = (n != 0 ? Math.sqrt(sqrfactor(n)) : 1);
var nk = (k != 1 ? Math.round(n / k / k) : n);
// ASSERT sqrt(n) = k sqrt(nn)
if (s < 0) {
s = -s;
r = -r;
k = -k
}
return (r != 0 || n != 0 || s != 1 ? showrns(r, (k < 0 ? -1 : 1), n, s)
+ (k != 1 && k != -1 && nk != 1 ? " = " + showrns(r, k, nk, s) : "") + " = " : "")
+ d + (c != d ? " = " + c : "")
}
;
function recrd(setIN) {
// if(!document.ans.Record.checked)return;
if (arguments.length == 0)setIN = false;
var rns = getRNS();
var r = rns.R, n = rns.N, s = rns.S,
d = getElementById("dec").value,
c = Cf.cftoString();
// if(setIN)
// {getElementById("cffixedIN").value=Cf.cf[0]+"; "+Cf.cf.slice(1).join(", ");
// getElementById("cfrepIN").value=Cf.cfrec.join(", ") }
Cf.cvgts();
putmsg(showrnsdc(r, n, s, d, c));
}
;
function _AuxWinHTML(lines) {
var TITLE = "", i = 0;
_AuxWinOpen("html");
if (beginswith(arguments[0], "OPT")) {
i = 1;
eval(arguments[0].substring(3))
}
;
with (_auxwin.document) {
writeln("", TITLE, "");
for (i; i < arguments.length; i++)
writeln(arguments[i]);
writeln("
",
"",
"
")
}
;
_auxwin.document.close()
}
function _AuxWinPlain(msg) {
_AuxWinOpen("plain");
with (_auxwin.document)
for (var i = 0; i < arguments.length; i++)
writeln(arguments[i]);
_auxwin.document.close()
}
// -------------
function isempty(fld, alt) {
return (fld.replace(/\s/g, "") == "" || (arguments.length == 2 ? fld == alt : false) )
}
;
function isINT(v, txt, e) {
var i;
v = v.replace(/\s/g, "");
if (v.indexOf(".") != -1)HALT(txt + " must be a whole number.\rUse the 'Decimal:' box for decimal number values.");
if (v == "") {
if (arguments.length >= 3) {
return e
} else {
return Number.NaN
}
}
;
ErrorAt = txt;
ErrorIn = v;
self.onerror = ERRORHandler;
i = eval(v);
self.onerror = DoERROR;
if (isNaN(i))HALT(txt + " is not a number.");
if (i.toString() != v && v.replace(/\d/g, "") == "")HALT("The number " + txt + " is too long:\r" + v);
return i
}
;
function isREAL(v, txt, e) {
v = v.replace(/,/g, "").replace(/\s/g, "");
if (v == "") {
if (arguments.length >= 3) {
return e
} else {
return Number.NaN
}
}
;
var r = parseFloat(v);
if (isNaN(r))HALT(txt + " is not a number.");
return r
}
;
function justify(s, fw, opt) {
var i;
if (typeof s != "string")s = s.toString();
if (arguments.length < 3)opt = "L";
if (opt == "L")for (i = s.length; i < fw; i++)s = s + " "
else if (opt == "R")for (i = s.length; i < fw; i++)s = " " + s;
else if (opt == "C")for (i = s.length; i < fw; i++)s = (i % 2 == 0 ? " " + s : s + " ");
return s
}
;
function SIGN(x) {
return (x == 0 ? 0 : x < 0 ? -1 : 1)
}
;
var Cf = new CF();
function setupCfIN(fxd, rep) {
Cf.reset();
Cf.cf = fxd.slice();
Cf.cfrec = rep.slice();
cfsetIN()
}
;
function cfsetIN() { // Cf -> cf IN flds
//putmsg("$cfsetIN");
var s = Cf.cf[0] + "; ";
if (Cf.cf.length == 1) {
getElementById("cffixedIN").value = s
}
else {
s = s + Cf.cf.slice(1).join(", ");
if (Cf.isPeriodic())s = s + ", ";
getElementById("cffixedIN").value = s;
}
;
getElementById("cfrepIN").value = (Cf.isPeriodic() ? Cf.cfrec.join(", ") : "" )
//if(Cf.cvgts.length==0)Cf.cvgts();
//putmsg(Cf.cftoString());
// putmsg(Cf.cvgtstoString());
}
;
function ratSHOW(Rat) { //alert("ratSHOW "+Rat);
setRNS(Rat.top, "", Rat.bot);
Sqrt2Dec(Rat.top, 0, Rat.bot);
}
;
function sqrfactorXX(n) {
var N = n;
if (n == 0)return 1;
if (n < 0)n = -n;
var sqrtn = Math.sqrt(n), floorsqrtn = Math.floor(sqrtn);
var nonsqr = Math.round((sqrtn - floorsqrtn) * (sqrtn - floorsqrtn) - floorsqrtn * floorsqrtn + 2 * floorsqrtn * sqrtn);
alert("sqrfactor of " + n + "=" + nonsqr + "*" + (n / nonsqr));
return Math.round(n / nonsqr)
}
;
function sqrfactor(n) {
var N = n;
if (n == 0)return 1;
if (n < 0)n = -n;
var f = 1, lim = Math.sqrt(n);
//if(debug)DBG("\rsqrfactor of "+n+ " lim="+lim);
if (lim > 100000)
if (!confirm("To simplify the fraction may take a while - do you still want simplification?")) {
return 1
}
;
while (n % 4 == 0) {
f = f * 4;
n = Math.round(n / 4)
}
;
//if(n<9)return f;
for (var i = 3, ii = 9; n >= ii && i <= lim; i = i + 2, ii = i * i) {//if(debug)DBG("sqrf i="+i+" ii="+ii+" n="+n);
while (n >= ii && n % ii == 0) {
f = f * ii;
n = Math.round(n / ii)
//if(debug)DBG(" ..f="+f+" n="+n)
}
}
;
//if(debug)DBG("sqrfactor of "+N+" = "+f+" *"+n);
return f
}
;
function simplifyrns(r, n, s) {
//check for common factors...
// var FF=sqrfactor(n);var F=Math.round(Math.sqrt(FF)); //n=F*F*(n/FF)
var g = gcd(r, Math.round(Math.sqrt(sqrfactor(gcd(n, s * s)))));
//if(debug)DBG("r="+r+" n="+n+" s="+s+" g="+g);
r = Math.round(r / g);
s = Math.round(s / g);
n = Math.round(n / (g * g));
return [r, n, s]
}
function sqrtSHOW(r, n, s) {
var rns = simplifyrns(r, n, s);
r = rns[0];
n = rns[1];
s = rns[2];
setRNS(r, n, s);
Sqrt2Dec();
}
;
var DECexpr;
function evalDec() {
var v;
DECexpr = getElementById("dec").value.replace(/ /g, "")
try {
with (Math) {
v = eval(DECexpr.replace(/Pi/ig, "PI"))
}
;
} catch (e) {
HALT(" The decimal expression cannot be evaluated - please correct it")
}
;
if (typeof v == "undefined")HALT(" Please type a number into the Decimal box");
if (v < 0)HALT("Decimal Value is negative");
if (!isFinite(v))HALT("The decimal is too large - sorry");
if (v == 0)HALT("The decimal value is too small - sorry");
if (v != getElementById("dec").value) {
putmsg(DECexpr + " = " + v); //getElementById("dec").value=v
}
;
Real2CF(v);
getElementById("dec").value = DECexpr;
return v
}
;
function Rat2CF(r, s) { //ASSERT n = 0
if (debug)DBG("Rat2CF(" + r + "," + s + ")");
if (arguments.length == 0) {
var rnsin = getRNS();
r = rnsin.R;
s = rnsin.S
}
var g = gcd(r, s);
if (g > 1) {
putmsg(r + "/" + s + " = ");
r = Math.round(r / g);
s = Math.round(s / g);
setRNS(r, 0, s)
}
;
rat2cf(r, s);
cfsetIN();
}
;
function Real2CF(r) {
//putmsg("$Real2CF: "+r);
var i = -1, nbterms, p10, r, q, R, S, rIN;
Cf.reset();
if (arguments.length == 1) {
rIN = r.toString()
}
else {
rIN = getElementById("dec").value.replace(/ /g, "")
r = isREAL(rIN, "Your Decimal entry")
}
;
if (isNaN(r))return;
if (r <= 0)HALT("Decimal values must be positive");
//putmsgto("res","dec ="+r);
nbterms = 0;
p10 = 0;
if (rIN.indexOf(".") != -1)p10 = rIN.length - rIN.indexOf(".") - 1
else p10 = 0;
//putmsg("rIN="+rIN+" p10="+p10);
R = parseInt(rIN.replace(/\./, ""));
S = Math.pow(10, p10)
setRNS(R, 0, S);
//putmsg("$Real2CF rat "+r+" = "+R+(S!=1?"/"+S:""));
Rat2CF()
// do
// { q=Math.floor(r);nbterms++
// if(r>0){Cf.append(q,true);
// if(!Cf.stopped&&r!=q){r=1/(r-q)}};
// putmsg("~~ "+r +" "+Math.abs(Cf.cvgt[Cf.cvgt.length-1].val/rIN-1));
// } while(!Cf.stopped &&Math.abs(Cf.cvgt[Cf.cvgt.length-1].val-rIN)>1e-9&&nbterms<30);
// cfsetIN();
recrd();
}
;
function Sqrt2Dec(r, n, s) { //alert("Sqrt2Dec");
if (arguments.length == 0) {
var rnsin = getRNS();
r = rnsin.R;
n = rnsin.N;
s = rnsin.S
}
;
var v = (r + Math.sqrt(n)) / s;
if (v < 0)HALT("The fraction is negative:" + v);
getElementById("dec").value = v;
if (debug)DBG("_____Sqrt to Dec ____ (" + r + " +sqrt " + n + ")/" + s + " = " + getElementById("dec").value)
}
;
function Sqrt2CF() {
var rnsin = getRNS();
var r = rnsin.R, n = rnsin.N, s = rnsin.S;
Sqrt2Dec(r, n, s);
if (n == 0) {
Rat2CF(r, s)
}
else {
SqrtPeriodicCF(r, n, s)
}
;
Cf.cvgts();
recrd();
}
;
function SqrtPeriodicCF(r, n, s) {
if (arguments.length == 0) {
var rnsin = getRNS();
r = rnsin.R;
n = rnsin.N;
s = rnsin.S
}
;
Cf.reset();
// putmsg("$sqrtperiodiccf: r="+r+" n="+n+" s="+s);
var R = new Array();
R[0] = r;
var S = new Array();
S[0] = s;
var sqt = Math.floor(Math.sqrt(n));
if (sqt * sqt == n) {
Rat2CF(r + sqt, s)
}
else {
if (n - R[0] * R[0] % S[0] != 0) {
R[0] = R[0] * Math.abs(S[0]);
n = n * S[0] * S[0];
S[0] = S[0] * Math.abs(S[0])
}
;
var j = 0;
for (i = 1; j == 0 && !Cf.cfOFLO; i++) {
Cf.append(Math.floor((R[i - 1] + Math.sqrt(n)) / S[i - 1]));
//putmsg("newterm: "+Cf.lastcf());
R[i] = Cf.lastcf() * S[i - 1] - R[i - 1];
S[i] = (n - R[i] * R[i]) / S[i - 1];
for (j = i - 1; j > 0 && (R[j] != R[i] || S[j] != S[i]); j--) {
}
;
}
;
if (!Cf.cfOFLO) { //Cf.cfperiodLWB=j;Cf.cfperiodUPB=i-2
//putmsg("Rec from "+j+".."+(i-2)+" Cf.cf="+Cf.cf);
Cf.cfrec = Cf.cf.slice(j, i - 1);
Cf.cf.length = j;
}
// putmsg(Cf.dump());putmsg("calling cvgts...");
Cf.cvgts();
// putmsg(Cf.dump())
// while(!Cf.stopped)Cf.append(Cf.cf[j++]);
}
;
cfsetIN();
//if(debug)DBG("______Sqrt to CF_____\r"+Cf.toString()+"\r"+getElementById("dec").value+" ("+eval((-r+Math.sqrt(n))/-s)+")");
}
;
function setCf(cfw, cff, cfr) {
// putmsg("$setCf: "+cfw+"; "+cff+" [ "+cfr.slice()+"]");
Cf.reset();
Cf.append(cfw);
for (var i = 0; i < cff.length; i++)
if (!isInt(cff[i])) HALT("This item in your CF is not a whole number:\r" + cff[i])
else if (cff[i] == 0 && i > 0) HALT("Only the first number in your CF can be 0.")
else if (cff[i] < 0) HALT("You cannot have negative numbers in your CF.\rI found " + cff[i])
else Cf.append(cff[i]);
Cf.cfrec = cfr.slice();
Cf.norm();
}
function setCfIN() { // cf IN flds -> Cf
var cfwf = getElementById("cffixedIN").value.replace(/\s/g, ""), cff, cfw,
cfr = getElementById("cfrepIN").value.replace(/\.\.\./, "").replace(/\s/g, ""),
semiat = cfwf.indexOf(";");
if (semiat == -1)halt("You must indicate the whole number part by a number followed by a semicolon(;)");
cfw = cfwf.slice(0, semiat);
cff = cfwf.slice(semiat + 1);
//putmsgto("res","whole="+cfw+" fxd="+cff+" rep="+cfr);
try {
cfw = eval(cfw);
if (!isInt(cfw))halt("The whole part before the semicolon is not a number: " + cfw)
}
catch (e) {
halt("The part before the semicolon is not a number: " + cfw)
}
;
try {
cff = eval("[" + cff + "]"); //alert("fxd part is "+telltype(cff));
if (telltype(cff) != "array")halt("only numbers and commas are allowed in the CF fixed part")
}
catch (e) {
halt("The CF is not a list of numbers after the semicolon")
}
;
try {
cfr = (cfr.length == 0 ? "" : eval("[" + cfr + "]"))
}
catch (e) {
halt("The repeating part must be a list numbers separated by a comma")
}
;
//if(telltype(cfr)!="array")halt("only numbers and commas are allowed in the CF repeating part");
//putmsg("$setCf from IN: w="+cfw+" fxd="+cff+" cfr="+cfr);
setCf(cfw, cff, cfr);
//putmsg("#setCf "+Cf.cftoString());
//clearxcpt('cfIN');
}
function revcfIN() { //putmsg("revcfin");
if (Cf.isUnset())setCfIN();
var cfw = Cf.cf[0], cff = Cf.cf.slice(1), cfr = Cf.cfrec.slice(), cfin = Cf.cftoString();
//putmsg("$revcfIN: "+cfw+";"+cff+"["+cfr+"]");
if (cfr.length > 0)halt("Cannot reverse a CF with a repeating part");
if (cfw != 0)cff.unshift(cfw);
cff.reverse();
cfw = cff.shift()
setCf(cfw, cff, cfr)
//putmsg("$revcfIN "+Cf.cftoString())
cfsetIN()
putmsg("Reverse of " + cfin + " = ");
recrd()
}
;
function recipcfIN() {
if (Cf.isUnset())setCfIN();
if (Cf.isZero())HALT("The CF is 0 so has no 1/CF form");
var cfw = Cf.cf[0], cff = Cf.cf.slice(1), cfr = Cf.cfrec.slice(), cfin = Cf.cftoString();
if (cfw == 0) {
if (cff.length == 0) {
cfw = cfr.shift();
cfr.push(cfw)
}
else cfw = cff.shift()
}
else {
cff.unshift(cfw);
cfw = 0
}
setCf(cfw, cff, cfr);
putmsg("1 / " + cfin + " = ");
cfsetIN();
recrd()
}
function Cfcvgts() {
//putmsg("Cf unset:"+Cf.isUnset());
if (Cf.isUnset())setCfIN();
//putmsg("Cf ="+Cf)
Cf.cvgts();
//putmsg(Cf.cftoString()+" has convergents:");
//getElementById("msgmorecf").innerHTML="";
putmsg(Cf.cvgtstoString())
}
;
function CF2Fract() {
setCfIN();
Cf.cvgts();
if (!Cf.isPeriodic())ratSHOW(Cf.toRAT())
else CF2Sqrt();
recrd();
}
;
function CF2Sqrt() {
var i;
var CFp = new CF(), CFnp = new CF();
//putmsgto("res","_______CF to sqrt__________\r");
CFp.cf = Cf.cfrec.slice();
CFp.cvgts();
CFnp.cf = Cf.cf.slice();
CFnp.cvgts();
if (CFp.stopped)HALT("The period of your CF is too long");
//putmsgto("res","CFp: "+CFp.toString());
//-----PERIODIC PART ---------
var penultR = CFp.cvgt[CFp.cf.length - 2], lastR = CFp.cvgt[CFp.cf.length - 1], R, N, S;
//putmsgto("res","Period expr from "+penultR+" "+lastR);
var p2 = penultR.top, q2 = penultR.bot, p1 = lastR.top, q1 = lastR.bot;
var r = p1 - q2, n = (p1 - q2) * (p1 - q2) + 4 * p2 * q1, s = 2 * q1;
var rns = simplifyrns(r, n, s);
r = rns[0];
n = rns[1];
s = rns[2];
var d1 = (r + Math.sqrt(n)) / s, d2 = (-r + Math.sqrt(n)) / (-s), dd = CFp.toDec(), pdec = d1;
//putmsgto("res","final p cvgts:"+penultR+","+lastR+"\r r="+r+" n="+n+" s="+s+
// " x="+d1+" or "+d2+
// " -------CHECK d1: RHS="+((p1*d1+p2)/(q1*d1+q2))+" d2:"+((p1*d2+p2)/(q1*d2+q2)));
if (Math.abs(d1 - dd) > Math.abs(d2 - dd)) {
r = -r;
s = -s;
pdec = d2
}
// putmsgto("res"," and nearest to "+dd+" is r="+r+" s="+s);
//----INITIAL NON-PERIODIC PART---------
//putmsgto("res","NONPERIODICPART: CFnp: "+CFnp.cftoString());
if (CFnp.cf.length > 0) {//for(i=0;i Math.abs(Dec2 - truedec)) {
R = -R;
S = -S
}
;
}
else {
R = r;
N = n;
S = s
}
;
sqrtSHOW(R, N, S);
if (debug)DBG("___dec showing___ " + getElementById("dec").value);
}
;
function CFalt() { //alert("CFalt "+cf.length+" elts;last is ="+cf[cf.length-1]+(cf[cf.length-1]==1));
//document.ans.res.value = document.ans.res.value+Cf.dump();
setCfIN();
Cf.altcf();
cfsetIN();
recrd();
}
;
function egSHOW() {
var which = getSEL("eg").value;
if (which == "") {
alert("Use the '" + getElementById("eg")[0].value + "' selector to choose which kind of example.")
}
else if (which == "egfr") {
setRNS(3, 0, 50);
clearxcpt('fract');
pushme('ratRbtn')
}
else if (which == "egdec") {
getElementById("dec").value = "0.123456790123";
clearxcpt('dec');
pushme('decRbtn');
}
else if (which == "egpi") {
getElementById("dec").value = "pi";
clearxcpt('dec');
pushme('decRbtn');
}
else if (which == "egsqrt") {
setRNS(0, 6, 1);
clearxcpt('fract');
pushme('ratRbtn');
}
else if (which == "egcfrat1") {
setupCfIN([0, 1, 2, 3], []);
clearxcpt('cfIN');
pushme('cfLbtn');
}
else if (which == "egcfrat2") {
setupCfIN([4, 3], [1, 2]);
clearxcpt('cfIN');
pushme('cfLbtn');
}
else if (which == "egeval1") {
getElementById("dec").value = "3*4.5 - 7.6/8";
clearxcpt('dec');
pushme('decRbtn')
}
else if (which == "egeval2") {
getElementById("dec").value = "pow((sqrt(5)+1)/2,3)";
clearxcpt('dec');
pushme('decRbtn')
}
else if (which == "egeval3") {
getElementById("dec").value = "cos(Pi*36/180)";
clearxcpt('dec');
pushme('decRbtn')
}
}
;
function clearxcpt(fld) {
if (arguments.length == 0)fld = "";
eval(btnoff);
if (fld.indexOf('cfIN') == -1) {
Cf.reset();
getElementById("cffixedIN").value = ""
getElementById("cfrepIN").value = ""
}
;
if (fld.indexOf("dec") == -1) {
getElementById("dec").value = ""
}
if (fld.indexOf("fract") == -1) {
setRNS("", "", "")
}
// if(fld.indexOf("res")==-1)getElementById("msgres").innerHTML=""
}
;
var btnoff = "";
function pushme(imgId) { //alert(wh.name+" "+wh.src);
var wh = getElementById(imgId);
if (!wh || !wh.src)halt("pushme " + imgId + " called: no btn found");
if (endswith(wh.src, "pushme.gif")) {
wh.src = wh.src.replace(/pushme/, '');
btnoff = ""
}
else {
wh.src = wh.src.replace(/\.gif/, "pushme.gif");
btnoff = "pushme('" + imgId + "')"
}
;
}
;
function dps(r, d) {
var x = (Math.floor(r * Math.pow(10, d)) / Math.pow(10, d)).toString();
for (var i = 1; x.length - x.indexOf(".") - 1 < d; i++)x += "0";
return x
}
function bestRATS(real) { /* find best rational approximations */
if (arguments.length == 0) {
real = getElementById("dec").value
}
var maxct = getInput("decapproxsz", "number of digits limit"),
showrat = getElementById('decapproxratQ').checked,
showcf = getElementById('decapproxcfQ').checked,
shownum = getElementById('decapproxnumQ').checked,
showerr = getElementById('decapproxerrQ').checked,
ct = 0;
//if(maxc>16)halt("The maximum number of digits is 16");
if (maxct < 1)halt("The number of approximations to find must be at least 1");
//alert(real);
var err = real, t, b, bestt, bestb, approxs = new Array();
bestt = Math.round(real), bestb = 1;
approxs[1] = new RAT(bestt, bestb);
putmsg(real + " is approximated best by:");
for (var b = 2, ct = 0; ct < maxct && Math.abs(err) > 1e-15; b++) {
t = Math.round(b * real);
if (Math.abs(real - bestt / bestb) > Math.abs(real - t / b)) {
bestt = t;
bestb = b; // approxs[approxs.length]=new RAT(t,b)
rat2cf(t, b);
ct++
err = eval(t / b) - real;
putmsg((showrat ? t + "/" + b : "") + (showcf ? " = " + Cf.cftoString() : "") +
((showrat || showcf) && shownum ? " = " : "") + (shownum ? dps(eval(t / b), 12) : "") +
(showerr ? " err=" + err : ""))
}
}
;
return approxs
}
;
function setRESsize(me) {
if (me.indexOf('Show') != -1) {
getElementById("msgres").style.width = "200%"
}
else {
getElementById("msgres").style.width = "100%"
}
}
;
///////////////////////////////////////////////////////////////////////
function putmsgto(outF, txt) {
if (arguments.length < 2)txt = "";
var olist = getElementById('msg' + outF); //alert("putmsg "+outF+" "+txt);
if (!olist)alert("putmsg->> " + txt)
else {
olist.innerHTML += txt + " ";
olist.scrollTop = olist.scrollHeight;
olist.scrollLeft = 0
}
;
}
;
function putmsg(txt, br) {
if (arguments.length == 0)txt = "";
if (arguments.length < 2)br = true;
// if(arguments.length>1)txt=arguments().join("");
var olist = getElementById('msg' + outF); //alert("putmsg "+outF);
if (!olist)alert("putmsg->> " + txt)
else {
olist.innerHTML += txt + (br ? " " : "");
olist.scrollTop = olist.scrollHeight;
olist.scrollLeft = 0
}
;
}
;
function clearForm(FormNm) {
var Form = document.getElementsByName(FormNm);
//if(Form.length>0)halt("@@ "+FormNm+" is used more than once!");
Form = Form[0];
//putmsg(objdump(Form)," ");
//alert("name: "+Form.name+" id: "+Form.id);
//alert(Form.elements.length+" elemens");
for (var i = 0; i < Form.elements.length; i++) { //if(!confirm(Form.elements[i].type+": "+Form.elements[i].id+"="+Form.elements[i].name))halt()
if (Form.elements[i].type == "text")
Form.elements[i].value = "";
}
}
;
function rat2cf(r, s) { // r/s
var t = r, b = s, i = -1, q;
Cf.reset();
do {
q = Math.floor(t / b);
r = t - q * b;
Cf.append(q);
t = b;
b = r;
} while (r /= 0 && !Cf.stopped);
}
;
function dobestapprox(r, maxd) {
if (arguments.length == 0) {
r = parseFloat(document.aprxF.aprxR.value);
maxd = parseInt(document.aprxF.aprxMAXD.value);
if (isNaN(r) || isNaN(maxd))HALT("数值到逼近或最大分母输入: 不是有效数字");
}
if (r < 0)r = -r;
//if(r>1)
// {r=r.toString();
// var rf=r.slice(r.indexOf("."));
// putmsg(r+"="+Math.floor(r)+"+"+rf);r = eval(rf)
// };
var err = 1, approxs = new Array(), padlenn = Math.max(3, Math.round(maxd * r).toString().length),
padlend = Math.max(3, maxd.toString().length);
putmsg("逼近 " + r + ":");
for (var d = (r < 0.5 ? 2 : 1); d <= maxd; d++) {
var n = Math.floor(d * r);
{
if (n == 0 || Math.abs(r - n / d) > Math.abs(r - (n + 1) / d))n++;
if (Math.abs(r - n / d) < Math.abs(err)) {
err = n / d - r;
approxs[approxs.length] = [n, d];
rat2cf(n, d);
putmsg(pad(n, padlenn) + n + "/" +
pad(d, padlend) + d + " = "
+ Number(n / d).toFixed(17)
+ " err= " + (err > 0 ? "+" : err == 0 ? " " : "") + Number(err).toFixed(16)
+ " CF: " + Cf.cftoString())
}
}
}
;
}