@@ -624,6 +624,253 @@ <h4 style="font-size:160%;margin:7px">Trigonometry</h4>
624624< br >
625625< br >
626626< br >
627+ < div >
628+ < script >
629+
630+ // ---- Trigonometry ----
631+ // A lightweight approximation-based lookup function
632+
633+
634+ // The lookup table
635+
636+ const trig = {
637+ "rad(1.6)" : {
638+ "sin" : "1"
639+ "cos" : "0"
640+ "tan" : "undefined"
641+ "deg" : "90.0"
642+ } ,
643+
644+
645+ "rad(1.467)" : {
646+ "sin" : "0.991"
647+ "cos" : "0.131"
648+ "tan" : "7.596"
649+ "deg" : "82.5"
650+
651+ }
652+
653+ }
654+
655+ // Helper: Finds closest rad(x) match for given function (sin or cos)
656+ function findClosestRad ( value , funcType ) {
657+ let closestKey = null ;
658+ let minDiff = Infinity ;
659+
660+ for ( const key in trig ) {
661+ if ( ! trig [ key ] [ funcType ] ) continue ;
662+ const keyMatch = key . match ( / r a d \( ( [ \d . ] + ) \) / ) ;
663+ if ( ! keyMatch ) continue ;
664+
665+ const radVal = parseFloat ( keyMatch [ 1 ] ) ;
666+ const diff = Math . abs ( radVal - value ) ;
667+
668+ if ( diff < minDiff ) {
669+ minDiff = diff ;
670+ closestKey = key ;
671+ }
672+
673+
674+ if ( closestKey ) {
675+ const approxVal = trig [ closestKey ] [ funcType ] . value ?. approx ?? trig [ closestKey ] [ funcType ] . value ;
676+ return `${ funcType } (${ closestKey } ) ≈ ${ approxVal } ` ;
677+ }
678+ }
679+
680+ function querySin ( input ) {
681+ // Normalize input: remove spaces, handle cases like "sin 0533" or "sin(0.533)"
682+ const match = input . match ( / s i n \s * \( ? ( [ 0 - 9 . ] + ) \) ? / i) ;
683+ if ( ! match ) return "Invalid input. Format: sin 0.533 or sin(0.533)" ;
684+
685+ const x = parseFloat ( match [ 1 ] ) ;
686+ const radKey = `rad(${ x . toFixed ( 3 ) } )` ;
687+
688+ // Case 1: Exact match
689+ if ( [ radKey ] && [ radKey ] . sin ) {
690+ return `sin(${ x } ) ≈ ${ trig [ radKey ] . sin . value ?. approx ?? trig [ radKey ] . sin . value } ` ;
691+ }
692+
693+ // Case 2A: 1.6 > x > 0.8 OR 0.1 > x > 0
694+ if ( ( x > 0.8 && x < 1.6 ) || ( x > 0 && x < 0.1 ) ) {
695+ // Find closest match in trig table
696+ const closest = findClosestRad ( x , 'sin' ) ;
697+ return `sin(${ x } ) ≈ ${ closest } ` ;
698+ }
699+
700+ // Case 2B: 0.8 > x > 0.1 → Reflect to cosine
701+ if ( x > 0.1 && x < 0.8 ) {
702+ const reflected = ( 1.6 - x ) . toFixed ( 3 ) ;
703+ const reflectedKey = `rad(${ reflected } )` ;
704+ if ( trig [ reflectedKey ] && trig [ reflectedKey ] . cos ) {
705+ return `sin(${ x } ) ≈ cos(${ reflected } ) ≈ ${ trig [ reflectedKey ] . cos . value ?. approx ?? trig [ reflectedKey ] . cos . value } ` ;
706+ }
707+ const closest = findClosestRad ( reflected , 'cos' ) ;
708+ return `sin(${ x } ) ≈ cos(${ reflected } ) ≈ ${ closest } ` ;
709+ }
710+
711+ }
712+
713+ function queryCos ( input ) {
714+ // Normalize and extract the value from input like "cos 0.533" or "cos(0.533)"
715+ const match = input . match ( / c o s \s * \( ? ( [ 0 - 9 . ] + ) \) ? / i) ;
716+ if ( ! match ) return ; // Invalid input format
717+
718+ const x = parseFloat ( match [ 1 ] ) ;
719+ const radKey = `rad(${ x . toFixed ( 3 ) } )` ;
720+
721+ // Case 1: Exact match
722+ if ( trig [ radKey ] && trig [ radKey ] . cos ) {
723+ return `cos(${ x } ) ≈ ${ trig [ radKey ] . cos . value ?. approx ?? trig [ radKey ] . cos . value } ` ;
724+ }
725+
726+ // Case 2A: 1.6 > x > 0.8 OR 0.1 > x > 0
727+ if ( ( x > 0.8 && x < 1.6 ) || ( x > 0 && x < 0.1 ) ) {
728+ const closest = findClosestRad ( x , 'cos' ) ;
729+ return `cos(${ x } ) ≈ ${ closest } ` ;
730+ }
731+
732+ // Case 2B: 0.8 > x > 0.1 → Reflect to sin(1.6 - x)
733+ if ( x > 0.1 && x < 0.8 ) {
734+ const reflected = ( 1.6 - x ) . toFixed ( 3 ) ;
735+ const reflectedKey = `rad(${ reflected } )` ;
736+
737+ if ( trig [ reflectedKey ] && trig [ reflectedKey ] . sin ) {
738+ return `cos(${ x } ) ≈ sin(${ reflected } ) ≈ ${ trig [ reflectedKey ] . sin . value ?. approx ?? trig [ reflectedKey ] . sin . value } ` ;
739+ }
740+
741+ const closest = findClosestRad ( reflected , 'sin' ) ;
742+ return `cos(${ x } ) ≈ sin(${ reflected } ) ≈ ${ closest } ` ;
743+ }
744+ }
745+
746+ function queryTan ( input ) {
747+ // Normalize and extract the value from input like "tan 0.533" or "tan(0.533)"
748+ const match = input . match ( / t a n \s * \( ? ( [ 0 - 9 . ] + ) \) ? / i) ;
749+ if ( ! match ) return ; // Invalid input format
750+
751+ const x = parseFloat ( match [ 1 ] ) ;
752+ const radKey = `rad(${ x . toFixed ( 3 ) } )` ;
753+
754+ // Case 1: Exact match
755+ if ( trig [ radKey ] && trig [ radKey ] . tan ) {
756+ return `tan(${ x } ) ≈ ${ trig [ radKey ] . tan . value ?. approx ?? trig [ radKey ] . tan . value } ` ;
757+ }
758+
759+ // Case 2A: 1.6 > x > 0.8 OR 0.1 > x > 0
760+ if ( ( x > 0.8 && x < 1.6 ) || ( x > 0 && x < 0.1 ) ) {
761+ const closest = findClosestRad ( x , 'tan' ) ;
762+ return `tan(${ x } ) ≈ ${ closest } ` ;
763+ }
764+
765+ // Case 2B: 0.8 > x > 0.1 → Reflect
766+ if ( x > 0.1 && x < 0.8 ) {
767+ const reflected = ( 1.6 - x ) . toFixed ( 3 ) ;
768+ const reflectedKey = `rad(${ reflected } )` ;
769+
770+ if ( trig [ reflectedKey ] && trig [ reflectedKey ] . tan ) {
771+ const reflectedTan = parseFloat ( trig [ reflectedKey ] . tan . value ?. approx ?? trig [ reflectedKey ] . tan . value ) ;
772+ return `tan(${ x } ) ≈ 1 / tan(${ reflected } )` ;
773+ }
774+
775+ const fallback = findClosestRad ( reflected , 'tan' ) ;
776+ return `tan(${ x } ) ≈ 1 / tan(${ reflected } ) ≈ 1 / (${ fallback } )` ;
777+ }
778+ }
779+
780+ function findClosestValueMatch ( value , funcType ) {
781+ let bestMatch = null ;
782+ let minDiff = Infinity ;
783+
784+ for ( const key in trig ) {
785+ const approx = trig [ key ] [ funcType ] ?. value ?. approx ?? trig [ key ] [ funcType ] ?. value ;
786+ if ( ! approx ) continue ;
787+
788+ const diff = Math . abs ( parseFloat ( approx ) - value ) ;
789+ if ( diff < minDiff ) {
790+ minDiff = diff ;
791+ bestMatch = { angle : key , approx } ;
792+ }
793+ }
794+
795+ return bestMatch ;
796+ }
797+
798+
799+ function queryAsin ( input ) {
800+ // Normalize and extract the value: "asin 0.5" or "asin(0.5)"
801+ const match = input . match ( / a s i n \s * \( ? ( [ 0 - 9 . / \s √ - ] + ) \) ? / i) ;
802+ if ( ! match ) return ; // Invalid format
803+
804+ const inputStr = match [ 1 ] . trim ( ) ;
805+ const x = parseFloat ( eval ( inputStr . replace ( / √ ( \d + ) / g, 'Math.sqrt($1)' ) ) ) ; // handles √2 etc.
806+
807+ if ( isNaN ( x ) || x <= 0 || x >= 1 ) return ; // asin(x) only defined for 0 < x < 1
808+
809+ // Case A: x > 0.707 or x < 0.1 → search sin column directly
810+ if ( x > 0.707 || x < 0.1 ) {
811+ const bestMatch = findClosestValueMatch ( x , 'sin' ) ;
812+ if ( bestMatch ) return `asin(${ inputStr } ) ≈ ${ bestMatch . angle } ` ;
813+ }
814+
815+ // Case B: 0.1 < x < 0.707 → search cos column and reflect
816+ const bestCosMatch = findClosestValueMatch ( x , 'cos' ) ;
817+ if ( bestCosMatch ) {
818+ const angleMatch = bestCosMatch . angle ;
819+ const angleNum = parseFloat ( angleMatch . match ( / [ \d . ] + / ) [ 0 ] ) ;
820+ const reflected = ( 1.6 - angleNum ) . toFixed ( 3 ) ;
821+ return `asin(${ inputStr } ) ≈ 1.6 - ${ angleMatch } ≈ rad(${ reflected } )` ;
822+ }
823+ }
824+
825+ function queryAcos ( input ) {
826+ // Normalize and extract the value: "acos 0.5" or "acos(0.5)"
827+ const match = input . match ( / a c o s \s * \( ? ( [ 0 - 9 . / \s √ - ] + ) \) ? / i) ;
828+ if ( ! match ) return ; // Invalid format
829+
830+ const inputStr = match [ 1 ] . trim ( ) ;
831+ const x = parseFloat ( eval ( inputStr . replace ( / √ ( \d + ) / g, 'Math.sqrt($1)' ) ) ) ;
832+
833+ if ( isNaN ( x ) || x <= 0 || x >= 1 ) return ; // acos(x) only defined for 0 < x < 1
834+
835+ // Case A: x < 0.707 or x > 0.996 → match cos directly
836+ if ( x < 0.707 || x > 0.996 ) {
837+ const bestMatch = findClosestValueMatch ( x , 'cos' ) ;
838+ if ( bestMatch ) return `acos(${ inputStr } ) ≈ ${ bestMatch . angle } ` ;
839+ }
840+
841+ // Case B: 0.707 < x < 0.996 → reflect from sin column
842+ const bestSinMatch = findClosestValueMatch ( x , 'sin' ) ;
843+ if ( bestSinMatch ) {
844+ const angleNum = parseFloat ( bestSinMatch . angle . match ( / [ \d . ] + / ) [ 0 ] ) ;
845+ const reflected = ( 1.6 - angleNum ) . toFixed ( 3 ) ;
846+ return `acos(${ inputStr } ) ≈ 1.6 - ${ bestSinMatch . angle } ≈ rad(${ reflected } )` ;
847+ }
848+ }
849+
850+ function queryAtan ( input ) {
851+ // Normalize and extract the value: "atan 0.5" or "atan(0.5)"
852+ const match = input . match ( / a t a n \s * \( ? ( [ 0 - 9 . / \s √ - ] + ) \) ? / i) ;
853+ if ( ! match ) return ; // Invalid format
854+
855+ const inputStr = match [ 1 ] . trim ( ) ;
856+ const x = parseFloat ( eval ( inputStr . replace ( / √ ( \d + ) / g, 'Math.sqrt($1)' ) ) ) ;
857+
858+ if ( isNaN ( x ) || x <= 0 || x >= 7.6 ) return ; // Domain cutoffs from your spec
859+
860+ // Case A: x > 1 or x < 0.089 → direct match
861+ if ( x > 1 || x < 0.089 ) {
862+ const bestMatch = findClosestValueMatch ( x , 'tan' ) ;
863+ if ( bestMatch ) return `atan(${ inputStr } ) ≈ ${ bestMatch . angle } ` ;
864+ }
865+
866+ // Case B: 0.089 < x < 1 → invert to 1/x and search tan table
867+ const reciprocal = 1 / x ;
868+ const bestMatch = findClosestValueMatch ( reciprocal , 'tan' ) ;
869+ if ( bestMatch ) return `atan(${ inputStr } ) ≈ ${ bestMatch . angle } ` ;
870+ }
871+
872+ </ script >
873+ </ div >
627874< div >
628875 < p style ="margin:12px; "> Area of a triangle:
629876< br >
@@ -1978,6 +2225,36 @@ <h6 style="font-size:160%;margin:7px">Area of a circle</h6>
19782225< br >
19792226< br >
19802227< br >
2228+ < label style ="margin:12px; " for ="test1 "> test1:</ label >
2229+ < input id ="test1 " type ="number " value ="1 " step ="any " />
2230+ < br >
2231+ < label style ="margin:12px; " for ="test2 "> test2:</ label >
2232+ < input id ="test2 " type ="number " value ="1 " step ="any " />
2233+
2234+ < script >
2235+ function test ( test1 , test2 ) {
2236+ return test1 + test2 * test3 ;
2237+ }
2238+
2239+ function updateTestVolume ( ) {
2240+ const test1 = parseFloat ( document . getElementById ( 'test1' ) . value ) ;
2241+ const test2 = parseFloat ( document . getElementById ( 'test2' ) . value ) ;
2242+ const test3 = queryTan ( 1.2 ) ;
2243+
2244+ if ( isNaN ( test1 ) || isNaN ( test2 ) ) {
2245+ document . getElementById ( 'test-volume' ) . innerText = '' ;
2246+ return ;
2247+ }
2248+
2249+ document . getElementById ( 'test-volume' ) . innerText =
2250+ `Volume: ${ testVolume ( test1 , test2 ) . toFixed ( 5 ) } cubic units` ;
2251+ }
2252+
2253+ document . getElementById ( 'test1' ) . addEventListener ( 'input' , updateTestVolume ) ;
2254+ document . getElementById ( 'test2' ) . addEventListener ( 'input' , updateTestVolume ) ;
2255+ </ script >
2256+ < p style ="margin:12px; " id ="test-volume "> </ p >
2257+ </ div >
19812258< div >
19822259< h17 style ="font-size:160%;margin:7px "> Geometry Calculator Android App</ h17 >
19832260< br >
0 commit comments